View Javadoc
1   /******************************************************************************
2    * BuckoVidLibImpl.java - Primary business object
3    * $Id: BuckoVidLibImpl.java,v 1.30 2015/05/14 03:00:03 dick Exp $
4    * 
5    * BuckoVidLib - The BuckoSoft Video Library
6    * Copyright(c) 2014 - Dick Balaska
7    * 
8    * $Log: BuckoVidLibImpl.java,v $
9    * Revision 1.30  2015/05/14 03:00:03  dick
10   * getPlexUrl is a property to be read, not hardcoded in.
11   *
12   * Revision 1.29  2015/05/11 01:57:54  dick
13   * /statistics wants a session so we don't count restricted movies.
14   *
15   * Revision 1.28  2015/05/10 19:03:58  dick
16   * Limit the anonymous user to 200 find results.
17   *
18   * Revision 1.27  2015/05/08 02:37:14  dick
19   * findVideosAndThings(key, max) returns videos, actors, directors, and writers
20   *
21   * Revision 1.26  2015/05/07 00:15:38  dick
22   * findMaxResults is a user config option.
23   *
24   * Revision 1.25  2015/05/06 17:04:09  dick
25   * Add findVideos().
26   * Remove unused unprotected video lookups.
27   *
28   * Revision 1.24  2015/05/06 03:36:53  dick
29   * hideRestricted allows a user with restricted access to temporarily turn it off.
30   *
31   * Revision 1.23  2015/05/05 04:26:00  dick
32   * Persist backgroundDelay and artShowDelay.
33   *
34   * Revision 1.22  2015/05/04 20:36:09  dick
35   * getBackgroundFit() needs to know if we are running the ArtShow, which may be different
36   * than the normal backgroundFit.
37   *
38   * Revision 1.21  2015/05/04 05:44:56  dick
39   * A custom UserWebSession is not really needed.  BSAccount creates an anonymous user,
40   * and user is never null. (User's account is null).
41   * Ancient bug in BSAccount created an empty user on create and set session's user to null on logout (instead of creating an empty anonymous user.
42   *
43   * Revision 1.20  2015/05/03 18:02:30  dick
44   * Add UserAttributes and backgroundFit handling.
45   *
46   * Revision 1.19  2015/05/01 12:46:11  dick
47   * Implement a thread to dynamically update the database from plex.
48   *
49   * Revision 1.18  2015/04/30 06:34:27  dick
50   * Getting lists of VideoBase is always protected by session.
51   *
52   * Revision 1.17  2015/04/30 03:18:04  dick
53   * Deal mostly with VideoBase. Only fetch full Video when we really need it.
54   * Protect all (most) calls to the restricted section of the library by session.
55   *
56   * Revision 1.16  2015/04/29 14:23:30  dick
57   * Don't convert a null object.
58   *
59   * Revision 1.15  2015/04/27 14:59:12  dick
60   * Support having restricted LibrarySections that you must have access to get to.
61   *
62   * Revision 1.14  2015/04/01 02:39:09  dick
63   * getDirectorVideos(key)
64   * stub getActorVideos and getWriterVideos.
65   * Build the video mappings of directors and genres so hibernate figures them out.
66   *
67   * Revision 1.13  2015/03/29 04:05:02  dick
68   * Improve statistics.
69   *
70   * Revision 1.12  2015/03/25 06:13:52  dick
71   * Keys are ints, not Strings.
72   *
73   * Revision 1.11  2015/03/21 09:21:13  dick
74   * getLibraryListVideos(key) returns one LibrarySection's videos.
75   *
76   * Revision 1.10  2014/11/01 08:05:06  dick
77   * Count TV episodes.
78   *
79   * Revision 1.9  2014/10/26 05:36:57  dick
80   * recentlyAdded status can display 2 videos.
81   *
82   * Revision 1.8  2014/10/23 05:00:10  dick
83   * WishList handling.
84   *
85   * Revision 1.7  2014/10/20 01:25:29  dick
86   * getRecentlyAdded().
87   *
88   * Revision 1.6  2014/10/19 01:54:59  dick
89   * Encapsulate access to the library through the LibraryManager.
90   *
91   * Revision 1.5  2014/10/17 08:11:19  dick
92   * Add the database and getFailedToRip().
93   *
94   * Revision 1.4  2014/10/12 07:24:46  dick
95   * Add the TV Shows to the library.
96   *
97   * Revision 1.3  2014/10/09 08:34:35  dick
98   * Use the Video as a key for the client, not just the image url.
99   *
100  * Revision 1.2  2014/10/08 04:25:44  dick
101  * Load the entire library and implement fetching an image.
102  *
103  * Revision 1.1  2014/10/07 02:28:05  dick
104  * Implement getSectionList().
105  */
106 package com.buckosoft.BuckoVidLib.business;
107 
108 import java.util.ArrayList;
109 import java.util.List;
110 import java.util.regex.Pattern;
111 
112 import javax.servlet.http.HttpServletRequest;
113 
114 import org.apache.commons.logging.Log;
115 import org.apache.commons.logging.LogFactory;
116 import org.springframework.beans.factory.annotation.Autowired;
117 import org.springframework.stereotype.Component;
118 
119 import com.buckosoft.BSAccount.BSAccountMan;
120 import com.buckosoft.BuckoVidLib.db.Database;
121 import com.buckosoft.BuckoVidLib.domain.Actor;
122 import com.buckosoft.BuckoVidLib.domain.Director;
123 import com.buckosoft.BuckoVidLib.domain.FailedToRip;
124 import com.buckosoft.BuckoVidLib.domain.LibrarySection;
125 import com.buckosoft.BuckoVidLib.domain.TVSeason;
126 import com.buckosoft.BuckoVidLib.domain.User;
127 import com.buckosoft.BuckoVidLib.domain.UserAttribute;
128 import com.buckosoft.BuckoVidLib.domain.UserWebSession;
129 import com.buckosoft.BuckoVidLib.domain.Video;
130 import com.buckosoft.BuckoVidLib.domain.VideoBase;
131 import com.buckosoft.BuckoVidLib.domain.WishList;
132 import com.buckosoft.BuckoVidLib.domain.Writer;
133 import com.buckosoft.BuckoVidLib.domain.rest.RestVideo;
134 import com.buckosoft.BuckoVidLib.domain.rest.admin.RestRefreshStatus;
135 import com.buckosoft.BuckoVidLib.util.ConfigManager;
136 import com.buckosoft.BuckoVidLib.util.DomainConverter;
137 import com.buckosoft.BuckoVidLib.web.ImageController;
138 import com.buckosoft.BuckoVidLib.web.plex.client.RestClientConstants;
139 
140 /** Implement the primary business object
141  * @author dick
142  * @since 2014-10-06
143  */
144 @Component
145 public class BuckoVidLibImpl implements BuckoVidLib {
146 	private final Log log = LogFactory.getLog(getClass());
147 
148 	static String plexUrl = null;
149 	
150 	@Autowired
151 	private	Database		db;
152 
153 	@Autowired
154 	private	LibraryManager	libraryManager;
155 	
156 	@Autowired
157 	BSAccountMan	bsAccountMan;
158 
159 	
160 	BuckoVidLibImpl() {
161 		log.info("Boot...");
162 	}
163 	@Override
164 	public List<LibrarySection> getSectionList() {
165 		return(libraryManager.getSectionList());
166 	}
167 	@Override
168 	public List<LibrarySection> getSectionList(boolean allowRestricted) {
169 		return(libraryManager.getSectionList(allowRestricted));
170 	}
171 
172 	@Override
173 	public RestVideo getRandomMovie(boolean allowRestricted) {
174 		VideoBase v = libraryManager.getRandomMovie(allowRestricted);
175 		if (v == null)
176 			return(null);
177 		return(DomainConverter.toRestVideo(v));
178 		
179 	}
180 
181 	/* (non-Javadoc)
182 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getVideoBaseFromKey(int, boolean)
183 	 */
184 	@Override
185 	public VideoBase getVideoBaseFromKey(int key, boolean allowRestricted) {
186 		return(libraryManager.getVideoBaseFromKey(key, allowRestricted));
187 	}
188 	/* (non-Javadoc)
189 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getVideoFromKey(int, boolean)
190 	 */
191 	@Override
192 	public Video getVideoFromKey(int key, boolean allowRestricted) {
193 		return(libraryManager.getVideoFromKey(key, allowRestricted));
194 	}
195 	@Override
196 	public List<FailedToRip>		getFailedToRip() {
197 		return(db.getFailedToRip());
198 	}
199 	
200 	/* (non-Javadoc)
201 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getWishList()
202 	 */
203 	@Override
204 	public List<WishList> getWishList() {
205 		return(db.getWishList());
206 	}
207 
208 	/* (non-Javadoc)
209 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getRecentlyAdded(int, boolean)
210 	 */
211 	@Override
212 	public List<VideoBase> getRecentlyAdded(int count, boolean allowRestricted) {
213 		return(libraryManager.getNewestVideos(count, allowRestricted));
214 	}
215 
216 	/* (non-Javadoc)
217 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#findVideos(java.lang.String, boolean, int)
218 	 */
219 	@Override
220 	public List<RestVideo> findVideosAndThings(String key, boolean allowRestricted, int maxReturned) {
221 		Pattern p = Pattern.compile("(?i).*"+key + ".*");
222 		List<RestVideo> rvl = new ArrayList<RestVideo>();
223 		List<VideoBase> vbl = libraryManager.findVideos(p, allowRestricted, maxReturned);
224 		for (VideoBase vb : vbl) {
225 			rvl.add(DomainConverter.toRestVideo(vb));
226 		}
227 		int remaining = maxReturned - rvl.size();
228 		if (remaining > 1) {		// +1 to leave a spot for the label.
229 			List<Actor> la = libraryManager.findActors(key, remaining-1);
230 			if (!la.isEmpty()) {
231 				remaining--;
232 				if (la.size() == 1)
233 					rvl.add(new RestVideo("Actor", RestVideo.STYPE_MARKER, RestVideo.STYPE_ACTOR));
234 				else
235 					rvl.add(new RestVideo("Actors", RestVideo.STYPE_MARKER, RestVideo.STYPE_ACTOR));
236 				for (Actor a : la) {
237 					rvl.add(new RestVideo(a.getName(), RestVideo.STYPE_ACTOR, a.getId()));
238 				}
239 				remaining -= la.size();
240 			}
241 		}
242 		if (remaining > 1) {		// +1 to leave a spot for the label.
243 			List<Director> ld = libraryManager.findDirectors(key, remaining-1);
244 			if (!ld.isEmpty()) {
245 				remaining--;
246 				if (ld.size() == 1)
247 					rvl.add(new RestVideo("Director", RestVideo.STYPE_MARKER, RestVideo.STYPE_DIRECTOR));
248 				else
249 					rvl.add(new RestVideo("Directors", RestVideo.STYPE_MARKER, RestVideo.STYPE_DIRECTOR));
250 				for (Director d : ld) {
251 					rvl.add(new RestVideo(d.getName(), RestVideo.STYPE_DIRECTOR, d.getId()));
252 				}
253 				remaining -= ld.size();
254 			}
255 		}
256 		if (remaining > 1) {		// +1 to leave a spot for the label.
257 			List<Writer> lw = libraryManager.findWriters(key, remaining-1);
258 			if (!lw.isEmpty()) {
259 				remaining--;
260 				if (lw.size() == 1)
261 					rvl.add(new RestVideo("Writer", RestVideo.STYPE_MARKER, RestVideo.STYPE_WRITER));
262 				else
263 					rvl.add(new RestVideo("Writers", RestVideo.STYPE_MARKER, RestVideo.STYPE_WRITER));
264 				for (Writer w : lw) {
265 					rvl.add(new RestVideo(w.getName(), RestVideo.STYPE_WRITER, w.getId()));
266 				}
267 				remaining -= lw.size();
268 			}
269 		}
270 		return(rvl);
271 	}
272 	/* (non-Javadoc)
273 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getLibraryListVideos(int)
274 	 */
275 	@Override
276 	public List<VideoBase> getLibraryListVideos(int key) {
277 		log.info("getLibraryListVideos key = " + key);
278 		return(libraryManager.getLibrarySectionVideos(key));
279 	}
280 
281 	/* (non-Javadoc)
282 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getDirectorVideos(int)
283 	 */
284 	@Override
285 	public List<VideoBase> getDirectorVideos(int key) {
286 		log.info("getDirectorVideos key = " + key);
287 		return(libraryManager.getDirectorVideos(key));
288 	}
289 
290 	/* (non-Javadoc)
291 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getWriterVideos(int)
292 	 */
293 	@Override
294 	public List<VideoBase> getWriterVideos(int key) {
295 		log.info("getWriterVideos key = " + key);
296 		return(libraryManager.getWriterVideos(key));
297 	}
298 	/* (non-Javadoc)
299 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getActorVideos(int)
300 	 */
301 	@Override
302 	public List<VideoBase> getActorVideos(int key) {
303 		log.info("getActorVideos key = " + key);
304 		return(libraryManager.getActorVideos(key));
305 	}
306 	/* (non-Javadoc)
307 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getLastUpdateTime()
308 	 */
309 	@Override
310 	public long getLastUpdateTime() {
311 		return(libraryManager.getLastUpdateTime());
312 	}
313 	/* (non-Javadoc)
314 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getTVEpisodeCount()
315 	 */
316 	@Override
317 	public int getTVEpisodeCount(boolean allowRestricted) {
318 		return(libraryManager.getTVEpisodeCount(allowRestricted));
319 	}
320 	/* (non-Javadoc)
321 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getMovieCount()
322 	 */
323 	@Override
324 	public int getMovieCount(boolean allowRestricted) {
325 		return(libraryManager.getMovieCount(allowRestricted));
326 	}
327 	/* (non-Javadoc)
328 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getTVShowCount()
329 	 */
330 	@Override
331 	public int getTVShowCount(boolean allowRestricted) {
332 		return(libraryManager.getTVShowCount(allowRestricted));
333 	}
334 
335 	/* (non-Javadoc)
336 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getTVSeasonFromKey(int)
337 	 */
338 	@Override
339 	public TVSeason getTVSeasonFromHashKey(int key) {
340 		return(libraryManager.getTVSeasonFromHashKey(key));
341 	}
342 	/* (non-Javadoc)
343 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#isAdmin(javax.servlet.http.HttpServletRequest)
344 	 */
345 	@Override
346 	public boolean isAdmin(HttpServletRequest request) {
347 		if (!this.bsAccountMan.isUserWebSession(request))
348 			return(false);
349 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
350 		log.debug("userWebSession = " + userWebSession);
351 		boolean admin = false;
352 		if (userWebSession.isLoggedIn()) {
353 			User u = (User)userWebSession.getUser();
354 			if (u.isAdmin())
355 				admin = true;
356 		}
357 		return(admin);
358 	}
359 
360 	/* (non-Javadoc)
361 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#isAllowRestricted(javax.servlet.http.HttpServletRequest)
362 	 */
363 	@Override
364 	public boolean isAllowRestricted(HttpServletRequest request) {
365 		if (!this.bsAccountMan.isUserWebSession(request))
366 			return(false);
367 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
368 		log.debug("userWebSession = " + userWebSession);
369 		boolean allowRestricted = false;
370 		if (userWebSession.isLoggedIn()) {
371 			User u = (User)userWebSession.getUser();
372 			if (u.isUnrestricted() && !u.isHideRestricted())
373 				allowRestricted = true;
374 		}
375 		return(allowRestricted);	
376 	}
377 
378 	/* (non-Javadoc)
379 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getHideRestricted(javax.servlet.http.HttpServletRequest)
380 	 */
381 	@Override
382 	public boolean isHideRestricted(HttpServletRequest request) {
383 		if (!this.bsAccountMan.isUserWebSession(request))
384 			return(true);
385 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
386 		log.debug("userWebSession = " + userWebSession);
387 		if (userWebSession.isLoggedIn()) {
388 			User u = (User)userWebSession.getUser();
389 			return(u.isHideRestricted());
390 		}
391 		return(true);
392 	}
393 	/* (non-Javadoc)
394 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#setHideRestricted(javax.servlet.http.HttpServletRequest, boolean)
395 	 */
396 	@Override
397 	public void setHideRestricted(HttpServletRequest request, boolean hideRestricted) {
398 		if (!this.bsAccountMan.isUserWebSession(request))
399 			return;
400 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
401 		log.debug("userWebSession = " + userWebSession);
402 		if (!userWebSession.isLoggedIn())
403 			return;
404 		User u = (User)userWebSession.getUser();
405 		u.setHideRestricted(hideRestricted);
406 			db.saveUserAttributes(u.getUserAttributes());
407 		
408 	}
409 	/* (non-Javadoc)
410 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getBackgroundFit(javax.servlet.http.HttpServletRequest)
411 	 */
412 	@Override
413 	public int getBackgroundFit(HttpServletRequest request, boolean artShow) {
414 		if (!this.bsAccountMan.isUserWebSession(request))
415 			return(2);	// no session = no art.  XXX hmm, what about when we want to return the raw image for google?
416 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
417 		log.debug("userWebSession = " + userWebSession);
418 		User u = (User)userWebSession.getUser();
419 		if (artShow && u.getBackgroundFit() == ImageController.bgGrey)
420 			return(u.getArtShowFit());
421 		return(u.getBackgroundFit());
422 	}
423 
424 	/* (non-Javadoc)
425 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#setBackgroundFit(javax.servlet.http.HttpServletRequest, int)
426 	 */
427 	@Override
428 	public void setBackgroundFit(HttpServletRequest request, int backgroundFit) {
429 		if (!this.bsAccountMan.isUserWebSession(request))
430 			return;
431 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
432 		log.debug("userWebSession = " + userWebSession);
433 		User u = (User)userWebSession.getUser();
434 		if (backgroundFit == ImageController.bgGrey && u.getBackgroundFit() != ImageController.bgGrey)
435 			u.setArtShowFit(u.getBackgroundFit());
436 		u.setBackgroundFit(backgroundFit);
437 		if (userWebSession.isLoggedIn())
438 			db.saveUserAttributes(u.getUserAttributes());
439 	}
440 	
441 
442 	/* (non-Javadoc)
443 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#setBackgroundDelays(javax.servlet.http.HttpServletRequest, int, int)
444 	 */
445 	@Override
446 	public void setBackgroundDelays(HttpServletRequest request,
447 			int backgroundDelay, int artShowDelay) {
448 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
449 		log.debug("userWebSession = " + userWebSession);
450 		User u = (User)userWebSession.getUser();
451 		u.setBackgroundDelay(backgroundDelay);
452 		u.setArtShowDelay(artShowDelay);
453 		if (userWebSession.isLoggedIn())
454 			db.saveUserAttributes(u.getUserAttributes());
455 	}
456 
457 
458 	/* (non-Javadoc)
459 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getFindMaxResults(javax.servlet.http.HttpServletRequest)
460 	 */
461 	@Override
462 	public int getFindMaxResults(HttpServletRequest request) {
463 		if (!this.bsAccountMan.isUserWebSession(request))
464 			return(10);	// no session
465 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
466 		log.debug("userWebSession = " + userWebSession);
467 		User u = (User)userWebSession.getUser();
468 		return(u.getFindMaxResults());
469 	}
470 	/* (non-Javadoc)
471 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#setFindMaxResults(javax.servlet.http.HttpServletRequest, int)
472 	 */
473 	@Override
474 	public void setFindMaxResults(HttpServletRequest request, int findMaxResults) {
475 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
476 		log.debug("userWebSession = " + userWebSession);
477 		User u = (User)userWebSession.getUser();
478 		if (!userWebSession.isLoggedIn() && findMaxResults > 200)
479 			findMaxResults = 200;
480 		u.setFindMaxResults(findMaxResults);
481 		if (userWebSession.isLoggedIn())
482 			db.saveUserAttributes(u.getUserAttributes());
483 	}
484 	/* (non-Javadoc)
485 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getUserAttributes(int)
486 	 */
487 	@Override
488 	public List<UserAttribute> getUserAttributes(int userId) {
489 		return(db.getUserAttributes(userId));
490 	}
491 	/* (non-Javadoc)
492 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#saveUserAttributes(java.util.List)
493 	 */
494 	@Override
495 	public void saveUserAttributes(List<UserAttribute> list) {
496 		db.saveUserAttributes(list);
497 	}
498 
499 	/* (non-Javadoc)
500 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#startRefreshLibraryFromPlex()
501 	 */
502 	@Override
503 	public void startRefreshLibraryFromPlex() {
504 		libraryManager.startRefreshLibraryFromPlex();
505 	}
506 	@Override
507 	public RestRefreshStatus getRefreshLibraryFromPlexStatus() {
508 		return(libraryManager.getRefreshLibraryFromPlexStatus());
509 	}
510 	/* (non-Javadoc)
511 	 * @see com.buckosoft.BuckoVidLib.business.BuckoVidLib#getPlexUrl()
512 	 */
513 	@Override
514 	public String getPlexUrl() {
515 		if (plexUrl == null) {
516 			plexUrl = ConfigManager.getString(RestClientConstants.REST_SERVER_URL_PROP_KEY, RestClientConstants.DEFAULT_REST_SERVER_LOCATION);
517 			if (!plexUrl.endsWith("/"))
518 				plexUrl += "/";
519 		}
520 		return(plexUrl);
521 	}
522 
523 
524 }