1 package org.musicontroller.dao;
2
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Calendar;
6 import java.util.Collection;
7 import java.util.Date;
8 import java.util.GregorianCalendar;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15 import java.util.TreeMap;
16 import java.util.Vector;
17 import java.util.Map.Entry;
18 import java.util.concurrent.CopyOnWriteArraySet;
19
20 import org.apache.log4j.Logger;
21 import org.hibernate.HibernateException;
22 import org.hibernate.Query;
23 import org.hibernate.Session;
24 import org.hibernate.SessionFactory;
25 import org.musicontroller.SongChangeListener;
26 import org.musicontroller.core.AIBag;
27 import org.musicontroller.core.Artist;
28 import org.musicontroller.core.Band;
29 import org.musicontroller.core.Contract_PS;
30 import org.musicontroller.core.Event;
31 import org.musicontroller.core.Instrument;
32 import org.musicontroller.core.Keyword;
33 import org.musicontroller.core.Keywordbag;
34 import org.musicontroller.core.Link;
35 import org.musicontroller.core.LinkableAbs;
36 import org.musicontroller.core.Playlist;
37 import org.musicontroller.core.Song;
38 import org.musicontroller.repair.ConsistencyChecker;
39 import org.musicontroller.security.Authority;
40 import org.musicontroller.security.Encrypter;
41 import org.musicontroller.security.IUser;
42 import org.musicontroller.security.Role;
43 import org.musicontroller.security.User;
44 import org.springframework.orm.hibernate3.HibernateTemplate;
45 import org.springframework.orm.hibernate3.SessionFactoryUtils;
46 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
47 import org.varienaja.util.DateTools;
48 import org.varienaja.util.DenseSet;
49 import org.varienaja.util.FileOperations;
50
51 public class HibernateDao extends HibernateDaoSupport implements Dao {
52 private static final Logger LOG = Logger.getLogger(HibernateDao.class);
53
54 private Set<SongChangeListener> _songChangeListeners;
55
56 public HibernateDao() {
57 _songChangeListeners = new CopyOnWriteArraySet<SongChangeListener>();
58 }
59
60 @SuppressWarnings("unchecked")
61 public List<Long> getSongIds() {
62 return getHibernateTemplate().find(
63 "select s.id from Song s order by s.id");
64 }
65
66 public Song getSongById(long id) {
67 return (Song) getHibernateTemplate().get(Song.class,id);
68 }
69
70 @SuppressWarnings("unchecked")
71 public List<Song> getSongsById(Collection<Long> ids) {
72 String sql = "from Song s where s.id in (:ids)";
73 List<Song> songlist = getHibernateTemplate().findByNamedParam(sql,
74 new String[]{"ids"},
75 new Object[] {ids});
76
77 return songlist;
78 }
79
80 public Band getBandById(long id) {
81 return (Band) getHibernateTemplate().get(Band.class,id);
82 }
83
84
85
86
87
88 @SuppressWarnings("unchecked")
89 public Band getBandByName(String name) {
90 String sql = "from Band b where lower(b.name)=:name order by b.inserted";
91 List<Band> bandlist = getHibernateTemplate().findByNamedParam(sql,
92 new String[] {"name"},
93 new Object[] {name.toLowerCase()});
94 return bandlist.size()==0 ? null : bandlist.get(0);
95 }
96
97 public Keyword getKeywordById(long id) {
98 return (Keyword) getHibernateTemplate().get(Keyword.class,id);
99 }
100
101 public Keywordbag getKeywordBagById(long id) {
102 return (Keywordbag) getHibernateTemplate().get(Keywordbag.class,id);
103 }
104
105 public Artist getArtistById(long id) {
106 return (Artist) getHibernateTemplate().get(Artist.class,id);
107 }
108
109 public AIBag getAIBagById(long id) {
110 return (AIBag) getHibernateTemplate().get(AIBag.class,id);
111 }
112
113 @SuppressWarnings("unchecked")
114 public Artist searchArtist(String artistfirstname, String artistlastname) {
115 if(artistlastname==null) {
116 return null;
117 }
118 StringBuilder sb = new StringBuilder();
119 sb.append("from Artist a where lower(a.lastname)=:lastname");
120 List<Artist> artistlist = null;
121 if(artistfirstname==null) {
122 sb.append(" and a.firstname is null");
123 artistlist = getHibernateTemplate().findByNamedParam( sb.toString(),
124 new String[] { "lastname" },
125 new Object[] { artistlastname.toLowerCase()});
126 } else {
127 sb.append(" and lower(a.firstname)=:firstname");
128 artistlist = getHibernateTemplate().findByNamedParam( sb.toString(),
129 new String[] { "lastname","firstname" },
130 new Object[] { artistlastname.toLowerCase(),artistfirstname.toLowerCase()});
131 }
132 Artist result = null;
133 if (artistlist.size() > 0) {
134 result = artistlist.get(0);
135 }
136 return result;
137 }
138
139 @SuppressWarnings("unchecked")
140 public AIBag getArtistAppearances(long artistid) {
141 String hql = "from AIBag bag " +
142 "left join bag.relations rel" +
143 " where rel.artist_id=:artistid";
144 Map<String,Object> params = new HashMap<String,Object>();
145 params.put("artistid", artistid);
146 List<AIBag> bags = search(hql, params, 0);
147 return bags.isEmpty()? null : bags.get(0);
148 }
149
150 public Instrument getInstrumentById(long id) {
151 return (Instrument) getHibernateTemplate().get(Instrument.class,id);
152 }
153
154 @SuppressWarnings("unchecked")
155 public Song getSong(Band band, String songname) {
156 Song result = null;
157 List<Song> bandlist = getHibernateTemplate().findByNamedParam("from Song s where s.name=:name and s.band=:band",
158 new String[]{"name","band"},new Object[]{LinkableAbs.normalizeName(songname),band});
159 if(bandlist.size()>0) {
160 result = bandlist.get(0);
161 }
162 return result;
163 }
164
165 @SuppressWarnings("unchecked")
166 public Playlist songsByBand(long bandid) {
167 Playlist result = new Playlist();
168
169 Map<String,Object> params = new HashMap<String,Object>();
170 params.put("bandid",bandid);
171 List<Song> l = search("from Song s where s.band.id=:bandid order by s.name",params,0);
172
173 result.setName("");
174 int counter = 1;
175 for (Song s : l) {
176 result.addSong(s,counter++);
177 }
178
179 return result;
180 }
181
182
183
184
185
186 @SuppressWarnings("unchecked")
187 public List search(String hql, Map<String,Object> params, int maxResults) {
188 return search(hql, params, maxResults, 0);
189 }
190
191
192
193
194
195 @SuppressWarnings("unchecked")
196 public List search(String hql, Map<String,Object> params, int maxResults, int offset) {
197 List result = new ArrayList();
198 try {
199 Query q = searchInternal(hql, params, maxResults, offset);
200 if(q!=null) {
201 result = q.list();
202 }
203 } catch (Exception e) {
204 LOG.error("Query failed: "+e.toString());
205 e.printStackTrace();
206 }
207 return result;
208 }
209
210
211
212
213
214
215
216
217
218
219 private Query searchInternal(String hql, Map<String,Object> params,
220 int maxResults, int offset) throws Exception {
221 Session session = SessionFactoryUtils.getSession(getSessionFactory(),
222 true);
223
224 try {
225 LOG.debug("Query: "+hql);
226 Query query = session.createQuery(hql);
227 if (maxResults > 0)
228 query.setMaxResults(maxResults);
229 if (offset > 0)
230 query.setFirstResult(offset);
231
232 if (params != null) {
233 LOG.debug("Setting query parameters");
234 for (Entry<String,Object> entry : params.entrySet()) {
235 String s = entry.getKey();
236 LOG.debug("Parameter: "+s);
237 Object value = entry.getValue();
238 LOG.debug("Value: "+value);
239 if (value instanceof Collection) {
240 query.setParameterList(s,(Collection<?>) value);
241 } else {
242 query.setParameter(s,value);
243 }
244 }
245 LOG.debug("All parameters set");
246 }
247
248 return query;
249 } catch (HibernateException e) {
250 LOG.error("Query failed: "+e.toString());
251 throw new Exception("Query failed. " + e.toString());
252 }
253 }
254
255 @SuppressWarnings("unchecked")
256 public Band searchBand(String bandname) {
257 Band result = null;
258 List<Band> results = getHibernateTemplate().findByNamedParam(
259 "from Band b where b.name=:name", "name", LinkableAbs.normalizeName(bandname));
260 if (results.size() > 0) {
261 result = results.get(0);
262 }
263 return result;
264 }
265
266 @SuppressWarnings("unchecked")
267 public Keyword searchKeyword(String keyworddesc) {
268 if(keyworddesc==null) {
269 return null;
270 }
271 Keyword result = null;
272 List<Keyword> results = getHibernateTemplate().findByNamedParam(
273 "from Keyword k where lower(k.name)=:name", "name", LinkableAbs.normalizeName(keyworddesc).toLowerCase());
274 if (results.size() > 0) {
275 result = results.get(0);
276 }
277 return result;
278 }
279
280 @SuppressWarnings("unchecked")
281 public List<Playlist> searchPlaylist(String playlistname) {
282 List<Playlist> results = getHibernateTemplate().findByNamedParam(
283 "from Playlist p where p.name=:name", "name", LinkableAbs.normalizeName(playlistname));
284 return results;
285 }
286
287 public void save(Band band) {
288 getHibernateTemplate().save(band);
289 }
290
291 public void save(Keyword keyword) {
292 getHibernateTemplate().save(keyword);
293 }
294
295 public void save(Keywordbag keywordbag) {
296 getHibernateTemplate().save(keywordbag);
297 }
298
299 public void save(Playlist playlist) {
300 getHibernateTemplate().save(playlist);
301 }
302
303 public void save(Link link) {
304 getHibernateTemplate().save(link);
305 }
306
307
308
309
310
311 public void save(Song song) {
312 boolean newSong = song.getId()==-1L;
313 getHibernateTemplate().save(song);
314 if (newSong) {
315 fireSongAdded(song);
316 } else {
317 fireSongChanged(song);
318 }
319 }
320
321 public void save(Artist artist) {
322 getHibernateTemplate().save(artist);
323 }
324
325 public void save(Instrument instr) {
326 getHibernateTemplate().save(instr);
327 }
328
329 public void save(AIBag aibag) {
330 getHibernateTemplate().save(aibag);
331 }
332
333 @SuppressWarnings("unchecked")
334 public IUser findUserByName(String username) {
335 IUser result = null;
336 List<IUser> results = getHibernateTemplate().findByNamedParam(
337 "from User u where u.nickname=:name", "name", username);
338 if (results.size() > 0) {
339 result = results.get(0);
340 }
341 return result;
342 }
343
344 private void appendSongIDsToPlaylist(Playlist playlist, List<Long> songids) {
345 if(songids==null) {
346 return;
347 }
348 int counter=playlist.getSongs().size()+1;
349 for (Long songid : songids) {
350 playlist.addSong(getSongById(songid),counter++);
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 @SuppressWarnings("unchecked")
371 private Playlist getTopSongsInternal(String title, int amount, final IUser user, final int eventkind, final Date daybegin, Date dayend, List<Keywordbag> bags) {
372 Playlist result = new Playlist();
373 Map<String,Object> params = new HashMap<String,Object>();
374 StringBuilder sb = new StringBuilder();
375
376 sb.append("select ev.song.id from Event ev where ev.eventkind=:kind ");
377 params.put("kind",eventkind);
378
379 if (user!=null) {
380 sb.append("and ev.user=:user ");
381 params.put("user",user);
382 }
383
384 if (daybegin!=null) {
385 sb.append("and ev.moment>=:daybegin ");
386 params.put("daybegin",daybegin);
387 result.setFilterBegin(daybegin);
388 if (dayend!=null) {
389 sb.append("and ev.moment<:dayend ");
390 params.put("dayend",dayend);
391 result.setFilterEnd(dayend);
392 }
393 }
394
395 if (bags!=null && bags.size()>0) {
396 sb.append("and ev.song.keywordbag.id in (");
397 Iterator<Keywordbag> it = bags.iterator();
398 while (it.hasNext()) {
399 sb.append(it.next().getId());
400 if (it.hasNext()) {
401 sb.append(",");
402 }
403 }
404 sb.append(") ");
405 }
406
407 sb.append("group by ev.song.id order by count(ev.id) desc, max(ev.moment) desc)");
408
409 List<Long> l = search(sb.toString(),params,amount);
410 this.appendSongIDsToPlaylist(result,l);
411 result.setName(title);
412 return result;
413 }
414
415
416
417
418
419
420
421
422 @SuppressWarnings("unchecked")
423 private Playlist getNewSongs(String title, Date daybegin, Date dayend) {
424 String hql = "from Song s where s.inserted>=:daybegin and s.inserted<:dayend " +
425 "order by s.inserted desc";
426
427 Map<String,Object> params = new HashMap<String,Object>();
428 params.put("daybegin",daybegin);
429 params.put("dayend",dayend);
430
431 List<Song> l = search(hql,params,0);
432
433 Playlist result = new Playlist();
434 result.setName(title);
435 int counter = 1;
436 for (Song s : l) {
437 result.addSong(s,counter++);
438 }
439 return result;
440 }
441
442
443
444
445
446
447
448
449 private Playlist getBrokenSongs(String title) {
450 final int maxSize = 250;
451 DenseSet errors = ConsistencyChecker.getBrokenSongIDs();
452 int size = errors.size();
453
454 Playlist result = new Playlist();
455 if (size>maxSize) {
456 title = title + " (first "+maxSize+" shown)";
457 }
458 result.setName(title);
459
460 int counter = 0;
461 while (counter<maxSize && counter<size) {
462 long songid = errors.get(counter);
463 Song s = getSongById(songid);
464 result.addSong(s,counter++);
465 }
466
467 return result;
468 }
469
470 private Playlist getTopSongs(String title, int amount, IUser user, int eventkind, Date daybegin, Date dayend) {
471 Playlist result = getTopSongsInternal(title,amount,user,eventkind,daybegin,dayend,null);
472
473 if (daybegin!=null && dayend!=null) {
474 Date olddaybegin = DateTools.previousMonthEnd(daybegin);
475 Date olddayend = DateTools.previousMonthEnd(dayend);
476
477
478 result.setPrevious( getTopSongsInternal(title,amount,user,eventkind,olddaybegin,olddayend,null) );
479 }
480
481 return result;
482 }
483
484 @SuppressWarnings("unchecked")
485 private Playlist getSongsPlayedAt(String title, IUser user, Date daybegin, Date dayend) {
486 Playlist result = new Playlist();
487
488 StringBuilder sb = new StringBuilder();
489 Map<String,Object> params = new HashMap<String,Object>();
490
491 sb.append("select e.song from Event e where e.moment>=:daybegin and e.moment<:dayend and e.eventkind=:kind ");
492 params.put("daybegin",daybegin);
493 params.put("dayend",dayend);
494 params.put("kind",Event.played);
495
496 if (user!=null) {
497 sb.append("and e.user=:user ");
498 params.put("user",user);
499 }
500 sb.append("order by e.moment desc");
501
502 List<Song> l = search(sb.toString(),params,0);
503
504 result.setName(title);
505 int counter = 1;
506 for (Song s : l) {
507 result.addSong(s,counter++);
508 }
509
510 return result;
511 }
512
513
514
515
516
517
518 @SuppressWarnings("unchecked")
519 public Playlist getPlaylistByName(String name) {
520 String sql = "from Playlist p where lower(p.name)=:name order by p.inserted";
521 List<Playlist> playlistlist = getHibernateTemplate().findByNamedParam(sql,
522 new String[] {"name"},
523 new Object[] {LinkableAbs.normalizeName(name).toLowerCase()});
524 return playlistlist.size()==0 ? null : playlistlist.get(0);
525 }
526
527 public Playlist getPlaylistById(long id, IUser user) {
528 PlaylistKey key = new PlaylistKey(id);
529 if (key.isSpecial()) {
530 return getSpecialPlaylist(key.getKind(),user,key.getFilter());
531 } else {
532 return (Playlist) getHibernateTemplate().get(Playlist.class,id);
533 }
534 }
535
536 private Playlist getSpecialPlaylist(int kind, IUser user, Date filter) {
537 if (user==null && kind>-1000) kind-=1000;
538
539 Calendar begin = new GregorianCalendar();
540 begin.set(Calendar.HOUR_OF_DAY,0);
541 begin.set(Calendar.MINUTE,0);
542 begin.set(Calendar.SECOND,0);
543
544 Calendar end = new GregorianCalendar();
545 end.set(Calendar.HOUR_OF_DAY,23);
546 end.set(Calendar.MINUTE,59);
547 end.set(Calendar.SECOND,59);
548
549 Date prevmonth = DateTools.previousMonthEnd(filter);
550 Date endofmonth = DateTools.endOfMonth(filter);
551 String dateDesc = DateTools.formatDate(filter,"MMMMM yyyy");
552
553
554 switch (kind) {
555 case -1 : return getTopSongs(user+"'s top 100",100,user,Event.played,null,null);
556 case -2 : return getSongsPlayedAt("Songs played today by "+user,user,begin.getTime(),end.getTime());
557 case -3 : return getTopSongs(user+"'s top 100 most requested songs",100,user,Event.requested,null,null);
558 case -4 : return getTopSongs(user+"'s top 25 of "+dateDesc,25,user,Event.played,prevmonth,endofmonth);
559 case -5 : return getTopSongs(user+"'s top 25 requested of "+dateDesc,25,user,Event.requested,prevmonth,endofmonth);
560 case -6 : return getTopSongs(user+"'s horrible 100",100,user,Event.skipped,null,null);
561 case -7 : return getForgottenSongs(user);
562 case -8 : {
563 begin.setTime(filter);
564 begin.set(Calendar.HOUR_OF_DAY,0);
565 begin.set(Calendar.MINUTE,0);
566 begin.set(Calendar.SECOND,0);
567 begin.set(Calendar.MONTH,0);
568 begin.set(Calendar.DAY_OF_MONTH, 1);
569
570 end.setTime(filter);
571 end.set(Calendar.HOUR_OF_DAY,23);
572 end.set(Calendar.MINUTE,59);
573 end.set(Calendar.SECOND,59);
574 end.set(Calendar.MONTH,11);
575 end.set(Calendar.DAY_OF_MONTH,31);
576 return getTopSongs(user+"'s top 100 in "+DateTools.formatDate(begin.getTime(), "yyyy"),100,user,Event.played,begin.getTime(),end.getTime());
577 }
578
579
580 case -1001 : return getTopSongs("Top 100",100,null,Event.played,null,null);
581 case -1002 : return getSongsPlayedAt("Songs played today",null,begin.getTime(),end.getTime());
582 case -1003 : return getTopSongs("Top 100 most requested songs",100,null,Event.requested,null,null);
583 case -1004 : return getTopSongs("Top 25 of "+dateDesc,25,null,Event.played,prevmonth,endofmonth);
584 case -1005 : return getTopSongs("Top 25 requested of "+dateDesc,25,null,Event.requested,prevmonth,endofmonth);
585 case -1006 : return getTopSongs("Horrible 100",100,null,Event.skipped,null,null);
586 case -1007 : return getForgottenSongs(null);
587
588 case -2001 : return getNewSongs("Songs inserted in "+dateDesc,prevmonth,endofmonth);
589 case -2002 : return getBrokenSongs("Songs that don't have a correct filesystem-link");
590 default : return null;
591 }
592 }
593
594
595
596
597
598
599
600
601
602
603
604
605
606 @SuppressWarnings("unchecked")
607 protected Playlist getForgottenSongs(IUser user) {
608 Playlist result = new Playlist();
609 result.setName(user + "'s forgotten songs");
610
611 StringBuilder hql = new StringBuilder();
612 hql.append("select s.id from Song s, Event e ");
613 hql.append("where s=e.song ");
614 hql.append("and s.id in ( ");
615 hql.append("select plays.song.id from Event plays where plays.user=:user and plays.eventkind=:eventkind group by plays.song.id having max(plays.moment)<:twoyearsago and count(plays.id)>=10");
616 hql.append(")");
617 if (user!=null) hql.append("and e.user=:user ");
618 hql.append("group by s.id, s.inserted ");
619 hql.append("having max(e.moment)<:twoyearsago ");
620 hql.append("order by (:twoyearsago-s.inserted)/count(e.id)");
621
622
623
624
625 Map params = new HashMap<String, Object>();
626 params.put("user", user);
627 params.put("eventkind", Event.played);
628 Date now = new Date();
629 Date twoyearsago = new Date(now.getTime()- (2L*365*24*60*60*1000) );
630 params.put("twoyearsago", twoyearsago);
631 List<Long> songIDs = search(hql.toString(), params, 25);
632
633 int counter = 0;
634 while (counter<songIDs.size()) {
635 long songid = songIDs.get(counter);
636 Song s = getSongById(songid);
637 result.addSong(s,++counter);
638 }
639
640 return result;
641 }
642
643 public IUser getUserById(long userId) {
644 return (IUser) getHibernateTemplate().get(User.class, userId);
645 }
646
647 @SuppressWarnings("unchecked")
648 public IUser findUserByNamePassword(String username, String password) {
649 if(username==null) {
650 return null;
651 }
652 IUser gebruiker = null;
653 String encryptedPassword = Encrypter.encrypt(password);
654 List<IUser> gebrList = getHibernateTemplate().findByNamedParam(
655 "from User p where p.loginname=:inlognaam and p.password=:password",
656 new String[] { "inlognaam", "password"},
657 new Object[] { username, encryptedPassword});
658 if (gebrList != null && !gebrList.isEmpty()) {
659 gebruiker = (IUser) gebrList.get(0);
660 }
661 return gebruiker;
662 }
663
664 @SuppressWarnings("unchecked")
665 public List<IUser> listUsers() {
666 return (List<IUser>) getHibernateTemplate().find("from User u order by u.loginname");
667 }
668
669 @SuppressWarnings("unchecked")
670 public List<IUser> findUserByLoginname(String loginname) {
671 if(loginname==null) {
672 return new Vector<IUser>();
673 }
674 return getHibernateTemplate().findByNamedParam(
675 "from User p where p.loginname=:inlognaam",
676 new String[]{"inlognaam"},
677 new String[]{loginname});
678 }
679
680 @SuppressWarnings("unchecked")
681 public IUser getUserByLoginname(String inlognaam) {
682 List<IUser> l = getHibernateTemplate().findByNamedParam("from User p where p.loginname=:inlognaam",
683 new String[]{"inlognaam"},
684 new Object[]{inlognaam});
685 return (l.size()>0) ? l.get(0) : null;
686 }
687
688 public void save(IUser user) {
689 getHibernateTemplate().saveOrUpdate(user);
690 }
691
692 public void delete(IUser user) {
693 getHibernateTemplate().delete(user);
694 }
695
696 public Role getRoleById(int roleId) {
697 return (Role) getHibernateTemplate().get(Role.class, roleId);
698 }
699
700 @SuppressWarnings("unchecked")
701 public List<Role> listRoles() {
702 return (List<Role>) getHibernateTemplate().find("from Role r order by r.name");
703 }
704
705 public void save(Role role) {
706 getHibernateTemplate().saveOrUpdate(role);
707 }
708
709 public Authority getAuthorityById(int authorityId) {
710 return (Authority) getHibernateTemplate().get(Authority.class, authorityId);
711 }
712
713 @SuppressWarnings("unchecked")
714 public List<Authority> listAuthorities() {
715 return (List<Authority>) getHibernateTemplate().find("from Authority a order by a.name");
716 }
717
718 public void save(Authority authority) {
719 getHibernateTemplate().saveOrUpdate(authority);
720 }
721
722 @SuppressWarnings("unchecked")
723 public List<Playlist> listPlaylists(Band band) {
724 return getHibernateTemplate().findByNamedParam(
725 "from Playlist p where p in (" +
726 "select distinct (ps.playlist) from Contract_PS ps, Song s "+
727 "where ps.song=s and s.band=:band) order by p.releasedate, p.name",
728 new String[]{"band"},
729 new Object[]{band});
730 }
731
732 @SuppressWarnings("unchecked")
733 public List<Playlist> listPlaylists(Song song) {
734 return getHibernateTemplate().findByNamedParam(
735 "from Playlist p where p in (" +
736 "select distinct (ps.playlist) from Contract_PS ps "+
737 "where ps.song=:song) order by p.releasedate, p.name",
738 new String[]{"song"},
739 new Object[]{song});
740 }
741
742 @SuppressWarnings("unchecked")
743 public List<Playlist> listPlaylists() {
744 return getHibernateTemplate().find("from Playlist p");
745 }
746
747 @SuppressWarnings("unchecked")
748 public List<Playlist> listPodcasts() {
749 return getHibernateTemplate().find("from Playlist p where p.link is not null");
750 }
751
752 public void evictSong(long songId) {
753 Song song = getSongById(songId);
754 getHibernateTemplate().evict(song);
755 }
756
757 public void evict(Object o) {
758 getHibernateTemplate().evict(o);
759 }
760
761 @SuppressWarnings("unchecked")
762 public List<Object[]> listBands(IUser user) {
763 Map<String,Object> params = new HashMap<String,Object>();
764 StringBuffer sb = new StringBuffer();
765 sb.append("select b.id, b.name, sum(case when ev.eventkind="+Event.played+" then 1 else 0 end), ");
766 sb.append("sum(case when ev.eventkind="+Event.skipped+" then 1 else 0 end)");
767 sb.append(" from Song s join s.band b left outer join s.events ev");
768 sb.append(" with ev.moment>:startdate ");
769
770 if(user!=null) {
771 sb.append("and ev.user.id=:userid");
772 params.put("userid",user.getId());
773 }
774 sb.append(" group by b.id, b.name, b.sortname");
775 sb.append(" order by b.sortname");
776
777 Calendar lastYear = new GregorianCalendar();
778 lastYear.add(Calendar.YEAR,-1);
779
780 params.put("startdate",lastYear.getTime());
781
782 return search(sb.toString(),params,0);
783 }
784
785
786
787
788
789 @SuppressWarnings("unchecked")
790 public List<Keyword> listKeywords() {
791 return getHibernateTemplate().find("from Keyword k");
792 }
793
794
795 @SuppressWarnings("unchecked")
796 public List<Object[]> listKeywords(IUser user, List<Keywordbag> bags) {
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 StringBuilder sb = new StringBuilder();
814
815 sb.append("select k.id, k.name, sum(case when ev.eventkind="+Event.played+" then 1 else 0 end), ");
816 sb.append("sum(case when ev.eventkind="+Event.skipped+" then 1 else 0 end)");
817 sb.append(" from Keywordbag kwb left join kwb.keywords k,");
818 sb.append(" Song s join s.keywordbag skwb left join s.events as ev ");
819 sb.append(" with ev.moment>:startdate and ev.user.id=:userid ");
820 sb.append(" where skwb=kwb and k.id is not null");
821
822 if (bags!=null) {
823
824
825 if (bags.size()==0) {
826 return null;
827 }
828 sb.append(" and kwb.id in(");
829 Iterator<Keywordbag> it = bags.iterator();
830 while (it.hasNext()) {
831 sb.append(it.next().getId());
832 if (it.hasNext()) {
833 sb.append(",");
834 }
835 }
836 sb.append(")");
837 }
838 sb.append(" group by k.id, k.name ");
839 sb.append(" order by k.name");
840
841 Calendar lastYear = new GregorianCalendar();
842 lastYear.add(Calendar.YEAR,-1);
843
844 Map<String,Object> params = new HashMap<String,Object>();
845 params.put("userid",user.getId());
846 params.put("startdate",lastYear.getTime());
847
848 return search(sb.toString(),params,0);
849 }
850
851 @SuppressWarnings("unchecked")
852 private List<Keywordbag> listKeywordbagsInternal(Collection<Keyword> keywords, boolean exactmatch) {
853 if (keywords==null) return null;
854 if (keywords.size()==0) return null;
855
856 Map<String,Object> params = new HashMap<String,Object>();
857
858 StringBuilder sb = new StringBuilder();
859 sb.append("select kwb.id from Keywordbag kwb");
860 if(exactmatch) {
861 sb.append(" where kwb.keywords.size=:size ");
862 } else {
863 sb.append(" where kwb.keywords.size>=:size ");
864 }
865
866 Iterator<Keyword> it = keywords.iterator();
867 int keywordcount = 0;
868 while (it.hasNext()) {
869 keywordcount++;
870 Keyword kw = it.next();
871 String paramname = "k"+String.valueOf(keywordcount);
872 sb.append(" and :");
873 sb.append(paramname);
874 sb.append(" in elements(kwb.keywords)");
875 params.put(paramname, kw);
876 }
877 params.put("size",keywordcount);
878
879 List<Long> kwbIds = search(sb.toString(),params,0);
880
881 if (kwbIds==null) {
882 return null;
883 } else {
884 List<Keywordbag> bags = new LinkedList<Keywordbag>();
885 for (Long kwbid : kwbIds) {
886 bags.add(getKeywordBagById(kwbid));
887 }
888 return bags;
889 }
890 }
891
892 public List<Keywordbag> listKeywordsBags(List<Keyword> keywords) {
893
894
895
896 return listKeywordbagsInternal(keywords,false);
897 }
898
899 public Keywordbag getKeywordsBag(Collection<Keyword> keywords) {
900
901
902
903 List<Keywordbag> bags = listKeywordbagsInternal(keywords,true);
904 return bags==null ? null : bags.size()==0 ? null : bags.get(0);
905 }
906
907 public Playlist songsByKeywordbags(List<Keywordbag> bags, IUser user, int maxResults) {
908 String title = "All songs with keywordbags...";
909 Date daybegin = DateTools.currentDate();
910 Calendar lastYear = new GregorianCalendar();
911 lastYear.add(Calendar.YEAR,-1);
912 return getTopSongsInternal(title,maxResults,user,Event.played,lastYear.getTime(),daybegin,bags);
913 }
914
915 @SuppressWarnings("unchecked")
916 private Playlist songsByKeywordsInternal(List<Keyword> keywords, IUser user) {
917
918
919
920
921
922 Playlist result = new Playlist();
923 if (keywords.size()==0) {
924 result.setName("");
925 } else {
926 StringBuilder sb = new StringBuilder();
927
928
929 sb.append("select s from Keywordbag kwb left join kwb.keywords as k, Song s where k in (:keywords) ");
930 sb.append("and s.keywordbag=kwb.id order by s.name");
931
932 Map<String, Object> params = new HashMap<String,Object>();
933 params.put("keywords", keywords);
934 List<Song> l = search(sb.toString(),params,250);
935
936 result.setName("All songs with keyword '"+keywords+"'");
937 int counter = 1;
938 for (Song s : l) {
939 result.addSong(s,counter++);
940 }
941 }
942
943 return result;
944 }
945
946 public Playlist songsByKeyword(long keywordid) {
947 Keyword keyword = getKeywordById(keywordid);
948 List<Keyword> keywords = new LinkedList<Keyword>();
949 keywords.add(keyword);
950 return songsByKeywordsInternal(keywords,null);
951 }
952
953 public Playlist songsByKeywords(List<Keyword> keywords, IUser user) {
954 return songsByKeywordsInternal(keywords,user);
955 }
956
957 public Playlist songsByKeywordIds(List<Long> keywordIds, IUser user) {
958 List<Keyword> keywords = new LinkedList<Keyword>();
959 if (keywordIds!=null) {
960 for (Long keywordid : keywordIds) {
961 Keyword keyword = getKeywordById(keywordid);
962 keywords.add(keyword);
963 }
964 }
965 return songsByKeywordsInternal(keywords,null);
966 }
967
968 @SuppressWarnings("unchecked")
969 public List<Keywordbag> listKeywordbags() {
970 return (List<Keywordbag>) getHibernateTemplate().find("from Keywordbag kbg");
971 }
972
973
974
975
976
977 @SuppressWarnings("unchecked")
978 public Playlist getNeighbours(long songid, IUser user) {
979
980
981
982
983
984
985
986
987
988 Playlist result = new Playlist();
989 Map<String,Object> params = new HashMap<String,Object>();
990 StringBuilder sb = new StringBuilder();
991
992 sb.append("select n.song.id from Event ev, Event n ");
993 sb.append("where ev.song.id=:songid and ev.eventkind in (:kinds1) ");
994 if (user!=null) {
995 sb.append("and ev.user=:user ");
996 params.put("user",user);
997 }
998 sb.append("and n.user=ev.user and n.eventkind in (:kinds2) ");
999 sb.append("and n.song<>ev.song and n.moment between ev.moment+'-0:10' and ev.moment+'0:10' ");
1000 sb.append("group by n.song.id ");
1001 sb.append("having count(n.moment)>=5 ");
1002 sb.append("order by count(n.moment) desc");
1003
1004 Collection<Integer> kinds = new LinkedList<Integer>();
1005 kinds.add(Event.played);
1006 params.put("kinds1",kinds);
1007 params.put("kinds2",kinds);
1008 params.put("songid",songid);
1009
1010 List<Long> l = search(sb.toString(),params,0);
1011 if(l!=null) {
1012 appendSongIDsToPlaylist(result,l);
1013 }
1014 result.setName("Neighbouring songs of song: "+songid);
1015 return result;
1016 }
1017
1018 @SuppressWarnings("unchecked")
1019 public List<Long[]> getDoubleSongs() {
1020
1021
1022
1023
1024
1025
1026
1027
1028 StringBuilder sb = new StringBuilder();
1029 sb.append("select s1.id, s2.id from Song s1, Song s2 ");
1030 sb.append("where s1.id<s2.id and lower(s1.name) like lower(s2.name) ");
1031 sb.append("and s1.band=s2.band and abs(s1.length-s2.length)<10000 ");
1032 sb.append("order by s1.name");
1033 List<Object[]> l = search(sb.toString(),new HashMap<String,Object>(),0);
1034
1035
1036
1037 List<Long[]> thePairs = new LinkedList<Long[]>();
1038 for (Object[] ll : l) {
1039 Long[] pair = new Long[2];
1040 pair[0] = (Long) ll[0];
1041 pair[1] = (Long) ll[1];
1042 thePairs.add(pair);
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 return thePairs;
1054 }
1055
1056 public void mergeSongs(Song keep, Song remove) {
1057
1058 try {
1059 keep.setInserted(new Date(Math.min(keep.getInserted().getTime(), remove.getInserted().getTime())));
1060 } catch (Exception e) {
1061 LOG.error("Not-fatal error setting date to oldest version when merging song: "+e);
1062 }
1063
1064
1065 for (Event ev : remove.getEvents()) {
1066 keep.addEvent(ev.getMoment(), ev.getUser(), ev.getEventkind());
1067 }
1068 save(keep);
1069
1070
1071 for (Playlist pl : listPlaylists(remove)) {
1072 for (Contract_PS ps : pl.getSongs()) {
1073 if (ps.getSong().equals(remove)) {
1074 ps.setSong(keep);
1075 }
1076 }
1077 save(pl);
1078 }
1079
1080
1081
1082
1083 File file = null;
1084 if (remove.getLink()!=null) {
1085 if (keep.getLink()!=null) {
1086 if (!remove.getLink().getFile().equals(keep.getLink().getFile())) {
1087 file = remove.getLink().getFile();
1088 }
1089 }
1090 }
1091 getHibernateTemplate().delete(remove);
1092 getHibernateTemplate().flush();
1093
1094
1095 fireSongDeleted(remove);
1096 if (file!=null) {
1097 if (!file.delete()) {
1098 LOG.error("Could not delete duplicate file: " + file.getAbsolutePath());
1099 }
1100 }
1101
1102 LOG.info("Song "+remove.getLink().getUrl()+" merged with song "+keep.getLink().getUrl()+".");
1103 }
1104
1105 @SuppressWarnings("unchecked")
1106 public void mergeBands(Band keep, Band remove) {
1107
1108 StringBuilder sb = new StringBuilder();
1109 sb.append("from Song s where s.band=:remove");
1110 Map<String, Object> params = new HashMap<String, Object>();
1111 params.put("remove", remove);
1112 List<Song> songs = search(sb.toString(), params,0);
1113
1114 for(Song s: songs) {
1115 s.setBand(keep);
1116 save(s);
1117 }
1118
1119 getHibernateTemplate().delete(remove);
1120 LOG.info("All songs from band "+remove.getName()+" moved to band "+keep.getName()+
1121 ", band "+remove.getName()+" deleted.");
1122 }
1123
1124 @SuppressWarnings("unchecked")
1125 public Instrument searchInstrument(String instrname) {
1126 Instrument result = null;
1127 List<Instrument> instrlist = getHibernateTemplate().findByNamedParam(
1128 "from Instrument i where lower(i.name)=:name",
1129 new String[] { "name" },
1130 new Object[] { LinkableAbs.normalizeName(instrname).toLowerCase() });
1131 if (instrlist.size() > 0) {
1132 result = instrlist.get(0);
1133 }
1134 return result;
1135 }
1136
1137 public int count(String hql, Map<String,Object> params) throws Exception {
1138 Query query = searchInternal(hql,params,0,0);
1139 int result = ((Long)query.iterate().next()).intValue();
1140 return result;
1141 }
1142
1143 @SuppressWarnings("unchecked")
1144 public List<Object[]> listMonthlySongCounts() {
1145 String hql = "select month(s.inserted), year(s.inserted), count(s.id) "+
1146 "from Song s "+
1147 "group by month(s.inserted),year(s.inserted) "+
1148 "order by year(s.inserted),month(s.inserted)";
1149
1150 return search(hql,null,0);
1151 }
1152
1153
1154
1155
1156
1157 @SuppressWarnings("unchecked")
1158 public Map<String, Integer> listMonthlyStatistics(IUser user) {
1159 String hql = "select year(e.moment), month(e.moment), e.eventkind, count(e.id) from Event e " +
1160 "where e.user=:user and e.eventkind>0 and e.moment is not null " +
1161 "group by year(e.moment), month(e.moment), e.eventkind";
1162 Map<String,Object> params = new HashMap<String,Object>();
1163 params.put("user", user);
1164 List<Object[]> iresult = search(hql, params, 0);
1165
1166
1167
1168 Map<String, Integer> result = new TreeMap<String, Integer>();
1169 for (Object[] obj : iresult) {
1170 String key = obj[0].toString() + "," + obj[1].toString() + "," + obj[2].toString();
1171 Integer value = 0;
1172 if (obj[3] instanceof Integer) {
1173 value = (Integer) obj[3];
1174 } else if (obj[3] instanceof Long) {
1175 value = ((Long) obj[3]).intValue();
1176 }
1177 result.put(key, value);
1178 }
1179 return result;
1180 }
1181
1182 @SuppressWarnings("unchecked")
1183 public List<Object[]> listNamableItems() {
1184 List<Object[]> result = search("select s.name, s.id, 's' from Song s",null,0);
1185 result.addAll(search("select i.name, i.id, 'i' from Instrument i",null,0));
1186 result.addAll(search("select k.name, k.id, 'k' from Keyword k",null,0));
1187 result.addAll(search("select a.lastname, a.id, 'a' from Artist a",null,0));
1188 result.addAll(search("select b.name, b.id, 'b' from Band b",null,0));
1189 result.addAll(search("select p.name, p.id, 'p' from Playlist p",null,0));
1190
1191 return result;
1192 }
1193
1194
1195 @SuppressWarnings("unchecked")
1196 public AIBag getMostUsedAIBag(Band band) {
1197 String hql = "select s.aibag.id from Song s where s.band=:band and s.aibag is not null group by s.aibag.id order by count(s.id) desc";
1198 Map<String,Object> params = new HashMap<String,Object>();
1199 params.put("band",band);
1200
1201 List<Long> bags = search(hql,params,1);
1202 if (bags.size()>0) {
1203 return getAIBagById(bags.get(0));
1204 } else {
1205 return null;
1206 }
1207 }
1208
1209 @SuppressWarnings("unchecked")
1210 public List<AIBag> listAIBags() {
1211 return (List<AIBag>) getHibernateTemplate().find("from AIBag ai");
1212 }
1213
1214 public void mergePlaylists(Playlist keep, Playlist delete) {
1215 if(keep==null || delete==null) {
1216 return;
1217 }
1218 for (Contract_PS songs : delete.getSongs()) {
1219 Song song = songs.getSong();
1220 keep.addSong(song, songs.getRowno());
1221 }
1222 save(keep);
1223 delete.getSongs().clear();
1224 save(delete);
1225 getHibernateTemplate().delete(delete);
1226 }
1227
1228 public void deleteArtist(Artist delete) {
1229 if(delete==null) {
1230 return;
1231 }
1232 getHibernateTemplate().delete(delete);
1233 }
1234
1235 public void deleteAiBag(AIBag delete) {
1236 if(delete==null) {
1237 return;
1238 }
1239 getHibernateTemplate().delete(delete);
1240 }
1241
1242
1243
1244
1245
1246 public SessionFactory getSessionFactory2() {
1247 return getSessionFactory();
1248 }
1249
1250
1251
1252
1253
1254 public void registerSongChangeListener(SongChangeListener listener) {
1255 _songChangeListeners.add(listener);
1256 }
1257
1258
1259
1260
1261
1262 private void fireSongAdded(Song song) {
1263 LOG.debug("Informing " + _songChangeListeners.size()+" listeners about new Song with id: " + song.getId());
1264 for (SongChangeListener listener : _songChangeListeners) {
1265 listener.onSongAdded(song);
1266 }
1267 }
1268
1269
1270
1271
1272
1273 private void fireSongDeleted(Song song) {
1274 LOG.debug("Informing " + _songChangeListeners.size()+" listeners about deleted Song with id: " + song.getId());
1275 for (SongChangeListener listener : _songChangeListeners) {
1276 listener.onSongDeleted(song);
1277 }
1278 }
1279
1280
1281
1282
1283
1284 private void fireSongChanged(Song song) {
1285 LOG.debug("Informing " + _songChangeListeners.size()+" listeners about changed Song with id: " + song.getId());
1286 for (SongChangeListener listener : _songChangeListeners) {
1287 listener.onSongChanged(song);
1288 }
1289 }
1290
1291 public HibernateTemplate getSupport() {
1292 return getHibernateTemplate();
1293 }
1294
1295 }