001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/presentation/tags/sakai_2-4-1/tool/src/java/org/sakaiproject/tool/presentation/PresentationTool.java $
003: * $Id: PresentationTool.java 14075 2006-08-28 18:21:09Z marquard@ched.uct.ac.za $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.presentation;
021:
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Vector;
025: import java.util.logging.Logger;
026:
027: import javax.faces.application.FacesMessage;
028: import javax.faces.context.FacesContext;
029:
030: import org.osid.id.IdManager;
031: import org.osid.shared.Id;
032: import org.sakaiproject.api.app.presentation.Presentation;
033: import org.sakaiproject.api.app.presentation.PresentationManager;
034: import org.sakaiproject.api.app.presentation.Slide;
035: import org.sakaiproject.exception.IdUnusedException;
036: import org.sakaiproject.exception.PermissionException;
037: import org.sakaiproject.exception.TypeException;
038: import org.sakaiproject.tool.api.Placement;
039: import org.sakaiproject.tool.cover.ToolManager;
040: import org.sakaiproject.util.EventObservingCourier;
041: import org.sakaiproject.util.ObservingCourier;
042:
043: import com.sun.faces.util.MessageFactory;
044:
045: /**
046: * <p>
047: * Presentation Tool
048: * </p>
049: *
050: * @author Mark Norton
051: * @version $Revision: 14075 $
052: */
053: public class PresentationTool {
054: /** Service Dependency: IdManager. */
055: protected IdManager idMgr = null;
056:
057: /** Service Dependency: Logger - eventually this will be the Sakai logger. */
058: protected Logger logger = null;
059:
060: /** Service Dependency: Presentation Service. */
061: protected PresentationManager prMgr = null;
062:
063: /** Private properties. */
064: protected Id id = null; // Id test field. No longer used.
065:
066: /** A list (PresentationView) of presentations to be displayed. */
067: protected List presentations = null;
068:
069: protected Presentation currentPresentation = null;
070:
071: protected List m_presentations = new Vector();
072:
073: /** These flags indicate our relationship to the show or slides. */
074: protected String currentMode = "main";
075:
076: protected int currentSlidePos = 0; // Local current slide if we are viewing
077:
078: /** Determines if this user has access only or has write ability */
079: protected boolean allowShow = false;
080:
081: /** Error message, etc.. */
082: String m_instruction_message = null;
083:
084: /** Courier for update * */
085: ObservingCourier m_observer = null;
086:
087: /**
088: * noarg constructor, required for managed beans. Note: You are NOT service injected at this point.
089: */
090: public PresentationTool() {
091:
092: }
093:
094: public String getInstructionMessage() {
095:
096: return m_instruction_message;
097: }
098:
099: public void setInstructionMessage(String message) {
100: m_instruction_message = message;
101: }
102:
103: protected FacesMessage getLocalizedMessage(
104: String resourceBundlePropertyName, String messageParameter) {
105: Object[] messageParameters = null;
106: if (messageParameter != null) {
107: messageParameters = new Object[] { messageParameter };
108: }
109: return MessageFactory.getMessage(FacesContext
110: .getCurrentInstance(), resourceBundlePropertyName,
111: messageParameters);
112: }
113:
114: private String getMsgFromBundle(String val) {
115: return getLocalizedMessage(val, null).getDetail();
116: }
117:
118: /**
119: * Our local decorated presentation object.
120: *
121: * @return
122: */
123: public class PresentationBean {
124: Presentation presentation;
125:
126: private boolean showing = false;
127:
128: // Constructor
129: PresentationBean(Presentation pres) {
130: this .presentation = pres;
131: this .showing = prMgr.isShowing(pres);
132: }
133:
134: // Actions
135: public String processActionListView() {
136: preAction();
137:
138: currentPresentation = getPresentation();
139: currentSlidePos = 0; // When switching presentations start at zero
140:
141: return switchMode("view");
142: }
143:
144: public String processActionListJoin() {
145: preAction();
146:
147: currentPresentation = getPresentation();
148: currentSlidePos = 0; // When switching presentations start at zero
149:
150: return switchMode("join");
151: }
152:
153: public String processActionListShow() {
154: preAction();
155:
156: currentPresentation = getPresentation();
157: currentSlidePos = 0; // When switching presentations start at zero
158: String msg = "";
159:
160: if (prMgr.startShow(currentPresentation)) {
161: return switchMode("show");
162: } else {
163: String newMode = processActionExit();
164: msg = getMsgFromBundle("pt_presentation_noStart");
165: setInstructionMessage(msg);
166: // setInstructionMessage("Unable to start show");
167: return switchMode(newMode);
168: }
169: }
170:
171: // Setters and getters
172: public Presentation getPresentation() {
173: return presentation;
174: }
175:
176: public boolean getShowing() {
177: // System.out.println("PresentationBean.getShowing() = "+showing);
178: return showing;
179: }
180:
181: public String getTitle() {
182: return this .presentation.getTitle();
183: }
184:
185: public String getModificationDate() {
186: return this .presentation.getModificationDate();
187: }
188:
189: public int getSlideCount() {
190: return this .presentation.getSlideCount();
191: }
192: }
193:
194: /**
195: * Set the decorated presentation list to be decorated objects of this list
196: *
197: * @param list
198: * The set of Presentations for the list.
199: */
200: protected void setPresentations(List list) {
201: // clear the list
202: m_presentations.clear();
203:
204: if (list == null)
205: return;
206:
207: // process each new entry
208: for (Iterator iPres = list.iterator(); iPres.hasNext();) {
209: Object o = iPres.next();
210: if (o instanceof Presentation) {
211: m_presentations.add(new PresentationBean(
212: (Presentation) o));
213: }
214: }
215: }
216:
217: protected List loadPresentations() {
218: List retval = null;
219: String msg = "";
220:
221: if (this .prMgr == null)
222: return null;
223:
224: try {
225: retval = this .prMgr.getPresentations();
226: } catch (IdUnusedException e) {
227: msg = getMsgFromBundle("pt_folder_noExist");
228: setInstructionMessage(msg);
229: // setInstructionMessage("Presentations folder does not exist in Resources");
230: return null;
231: } catch (TypeException e) {
232: msg = getMsgFromBundle("pt_folder_typeException");
233: setInstructionMessage(msg);
234: // setInstructionMessage("Access to Presentations folder failed with a TypeException");
235: return null;
236: } catch (PermissionException e) {
237: msg = getMsgFromBundle("pt_folder_noPermission");
238: setInstructionMessage(msg);
239: // setInstructionMessage("You do not have permission on the Presentations folder");
240: // System.out.println("PermissionException");
241: }
242: return retval;
243: }
244:
245: /**
246: * Refresh the list of presentations.
247: */
248: protected void refreshPresentations() {
249: // System.out.println("PresentationTool.refreshPresentations()");
250: if (presentations == null) {
251: presentations = loadPresentations();
252: if (presentations != null) {
253: if (presentations.size() > 0) {
254: Presentation pres = (Presentation) presentations
255: .get(0);
256: allowShow = prMgr.allowUpdate(pres);
257: }
258: }
259: }
260: // System.out.println("PresentationTool.refreshPresentations() ok to show="+allowShow);
261:
262: // use this to populate our decorated list
263: setPresentations(presentations);
264: }
265:
266: /**
267: * Return an EventsObservingCourier for the particular reference area.
268: *
269: * @param pattern
270: */
271: protected ObservingCourier makeResourceCourier(String pattern) {
272: // get the current tool placement
273: Placement placement = ToolManager.getCurrentPlacement();
274:
275: // location is just placement
276: String location = placement.getId();
277:
278: // the html element to update on delivery (all of me!)
279: String elementId = null;
280:
281: EventObservingCourier observer = new EventObservingCourier(
282: location, elementId, pattern);
283: return observer;
284: }
285:
286: /**
287: * Return the IdManager service.
288: */
289: public IdManager getIdMgr() {
290: return this .idMgr;
291: }
292:
293: /**
294: * Set the IdManager service.
295: */
296: public void setIdMgr(IdManager mgr) {
297: // System.out.println("Presentation Tool Injected Id manager " + mgr);
298: this .idMgr = mgr;
299: }
300:
301: /**
302: * Return the PresentationManager service.
303: */
304: public PresentationManager getPrMgr() {
305: return this .prMgr;
306: }
307:
308: /**
309: * Set the PrsentationManager service.
310: */
311: public void setPrMgr(PresentationManager mgr) {
312: // System.out.println("Presentation Tool Injected presentation manager " + mgr);
313: this .prMgr = mgr;
314: }
315:
316: /**
317: * Return the list of presentations (decorated). Also check to see if the user is allowed to update the content area so the proper buttons are made available.
318: */
319: public List getPresentations() {
320: // System.out.println("PresentationTool.getPresentations()");
321:
322: refreshPresentations();
323:
324: return m_presentations;
325: }
326:
327: /**
328: * Get the current slide.
329: *
330: * @return curent Slide
331: */
332: public Slide getSlide() {
333: String msg = "";
334:
335: if (currentPresentation == null) {
336: msg = getMsgFromBundle("pt_presentation_noPresentation");
337: setInstructionMessage(msg);
338: // setInstructionMessage("There is no presentation currently showing.");
339:
340: msg = getMsgFromBundle("pt_log_getSlide_noPresentation");
341: logInfo(msg);
342: return null;
343: }
344: if (currentMode.equals("view")) {
345: int maxSlide = currentPresentation.getSlideCount();
346: if (currentSlidePos > (maxSlide - 1))
347: currentSlidePos = maxSlide - 1;
348: if (currentSlidePos < 0)
349: currentSlidePos = 0;
350: return currentPresentation.getSlide(currentSlidePos);
351: } else { // For join and show
352: return prMgr.getCurrentSlide(currentPresentation);
353: }
354: }
355:
356: /**
357: * Determine whether or not the current presentation is showing.
358: *
359: * @return True is the current presentation is showing.
360: */
361: public boolean getIsShowing() {
362: if (currentPresentation == null)
363: return false;
364: boolean retval = prMgr.isShowing(currentPresentation);
365: // System.out.println("getIsShowing()="+retval);
366: return retval;
367: }
368:
369: public boolean getAllowShow() {
370: if (currentPresentation != null) {
371: allowShow = prMgr.allowUpdate(currentPresentation);
372: // System.out.println("PresentationTool.getAllowShow(current)="+allowShow);
373: } else { // Refresh the presentations - will check and set access status
374: refreshPresentations();
375: }
376: // System.out.println("PresentationTool.getAllowShow(current)="+allowShow);
377:
378: return this .allowShow;
379: }
380:
381: public int getSlideCount() {
382: if (currentPresentation == null)
383: return 0;
384: return currentPresentation.getSlideCount();
385: }
386:
387: /**
388: * Return a string indicating the current show position as an example: "1 of 5" the expectation is that there will be a message like Viewing: 1 of 5 Viewing: No current presentation
389: *
390: * @return Position Insdicator String
391: */
392: public String getShowPosition() {
393: String retval = "";
394: String msg = "";
395: if (currentPresentation == null) {
396: msg = getMsgFromBundle("pt_presentation_noPresentation");
397: setInstructionMessage(msg);
398: // setInstructionMessage("There is no presentation currently showing.");
399:
400: msg = getMsgFromBundle("pt_log_getSlide_noPresentation");
401: logInfo(msg);
402: // logInfo("getSlide() called with no current presentation");
403:
404: msg = getMsgFromBundle("pt_presentation_noCurrent");
405: return msg;
406: }
407:
408: // Since we are being called at the beginning of nearly every render,
409: // we indicate that any pending events can be discarded.
410: // TODO: At some point, this should be placed somewhere that it is not a
411: // side-effect but instead an explicit call
412: if (m_observer != null) {
413: m_observer.justDelivered();
414: }
415:
416: int maxSlide = currentPresentation.getSlideCount();
417: if (currentMode.equals("view")) {
418: if (currentSlidePos > (maxSlide - 1))
419: currentSlidePos = maxSlide - 1;
420: if (currentSlidePos < 0)
421: currentSlidePos = 0;
422: retval = retval + (currentSlidePos + 1);
423: } else { // For join and show
424: int tmpSlide = prMgr
425: .getCurrentSlideNumber(currentPresentation);
426: retval = retval + (tmpSlide + 1);
427: }
428: retval = retval + " of " + maxSlide;
429: return retval;
430: }
431:
432: /**
433: * Do general setup for action methods.
434: */
435: private void preAction() {
436: setInstructionMessage(null);
437: }
438:
439: /**
440: * Helper for switching to "join", "view", or "show" modes.
441: *
442: * @return the navigation outcome.
443: */
444: private String switchMode(String newMode) {
445: String msg = "";
446: // System.out.println("switchMode from="+currentMode+" newMode="+newMode);
447:
448: // If Switching into join mode with a valid presentation, set up an observer
449: // to watch for the changes
450:
451: if (newMode.equals("join") && !currentMode.equals("join")
452: && currentPresentation != null) {
453: // System.out.println("Switching into join mode");
454: String pattern = prMgr.getReference(currentPresentation);
455: // System.out.println("pattern="+pattern);
456:
457: m_observer = makeResourceCourier(pattern);
458: }
459:
460: // Switch modes
461: currentMode = newMode;
462:
463: if (!currentMode.equals("join") && m_observer != null) {
464: // System.out.println("Turning off observer="+m_observer);
465: m_observer.disable();
466: m_observer = null;
467: }
468:
469: if (currentPresentation != null)
470: return currentMode;
471:
472: if (!newMode.equals("main")) {
473: msg = getMsgFromBundle("pt_presentation_isNull");
474: setInstructionMessage(msg);
475: // setInstructionMessage("Error - Current presentation is null");
476:
477: // TODO: developer handler for dynamic message below.
478:
479: logInfo("Presentation tool, no presentation while switching to "
480: + newMode);
481: this .prMgr.clearPresentationCache();
482: presentations = null;
483: currentMode = "main";
484: }
485:
486: return currentMode;
487: }
488:
489: /**
490: * Process the "View" action.
491: *
492: * @return the navigation outcome.
493: */
494: public String processActionView() {
495: preAction();
496: return switchMode("view");
497: }
498:
499: /**
500: * Process the "Join" action.
501: *
502: * @return the navigation outcome.
503: */
504: public String processActionJoin() {
505: preAction();
506:
507: return switchMode("join");
508: }
509:
510: /**
511: * Process the "Refresh Presentations" action. This causes the presentation list to be reloaded.
512: *
513: * @return the navigation outcome.
514: */
515: public String processActionRefreshPresentations() {
516: preAction();
517: this .prMgr.clearPresentationCache();
518: presentations = null;
519: refreshPresentations();
520: return switchMode("main");
521: }
522:
523: /**
524: * Handle a refresh view event. This is only needed while watching a presentation.
525: */
526: public String processActionRefresh() {
527: preAction();
528: return currentMode;
529: }
530:
531: /**
532: * Process the "End" action. This causes the active show to end.
533: *
534: * @return the navigation outcome.
535: */
536: public String processActionEnd() {
537: preAction();
538: String msg = "";
539: if (currentPresentation == null) {
540: msg = getMsgFromBundle("pt_presentation_noLongerShowing");
541: setInstructionMessage(msg);
542: // setInstructionMessage("Current presentation no longer showing.");
543: } else if (!prMgr.stopShow(currentPresentation)) {
544: msg = getMsgFromBundle("pt_presentation_stopProblem");
545: setInstructionMessage(msg);
546: // setInstructionMessage("Problem encountered while stopping presentation.");
547: }
548: currentPresentation = null;
549: this .prMgr.clearPresentationCache();
550: presentations = null;
551: return switchMode("main");
552: }
553:
554: /**
555: * Process the "Next" action. This causes the current show to move to the next slide. It will not go past the end of the show.\
556: *
557: * @return the navigation outcome.
558: */
559: public String processActionNext() {
560: preAction();
561: String msg = "";
562:
563: if (currentPresentation == null) {
564: String retval = processActionExit();
565: msg = getMsgFromBundle("pt_presentation_noLongerShowing");
566: setInstructionMessage(msg);
567: // setInstructionMessage("Current presentation no longer showing.");
568: return retval;
569: }
570:
571: if (currentMode.equals("view")) {
572: currentSlidePos++;
573: int maxSlide = currentPresentation.getSlideCount();
574: if (currentSlidePos > (maxSlide - 1))
575: currentSlidePos = maxSlide - 1;
576: if (currentSlidePos < 0)
577: currentSlidePos = 0;
578: } else { // For join and show
579: prMgr.advanceShow(currentPresentation);
580: }
581:
582: return currentMode;
583: }
584:
585: /**
586: * Process the "Previous" action. This causes the current show to move the current slide to the previous slide. It will not go past the first slide.
587: *
588: * @return the navigation outcome.
589: */
590: public String processActionPrevious() {
591: preAction();
592: String msg = "";
593: if (currentPresentation == null) {
594: String retval = processActionExit();
595: msg = getMsgFromBundle("pt_presentation_noLongerShowing");
596: setInstructionMessage(msg);
597: // setInstructionMessage("Current presentation no longer showing.");
598: return retval;
599: }
600:
601: if (currentMode.equals("view")) {
602: currentSlidePos--;
603: int maxSlide = currentPresentation.getSlideCount();
604: if (currentSlidePos > (maxSlide - 1))
605: currentSlidePos = maxSlide - 1;
606: if (currentSlidePos < 0)
607: currentSlidePos = 0;
608: } else { // For join and show
609: prMgr.backShow(currentPresentation);
610: }
611:
612: return currentMode;
613: }
614:
615: /**
616: * Process the "Exit" action. Handle the exit even out of the viewer page.
617: *
618: * @return the navigation outcome.
619: */
620: public String processActionExit() {
621: preAction();
622: currentPresentation = null;
623: this .prMgr.clearPresentationCache();
624: presentations = null;
625: return switchMode("main");
626: }
627:
628: private void logInfo(String message) {
629: System.out.println("INFO/Presentation Tool:" + message);
630: }
631:
632: }
633:
634: /**************************************************************************************************************************************************************************************************************************************************************
635: * $Footer: $
636: *************************************************************************************************************************************************************************************************************************************************************/
|