package kornell.scorm.client.scorm12; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import com.google.gwt.core.shared.GWT; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.Timer; import com.google.web.bindery.event.shared.EventBus; import kornell.api.client.KornellSession; import kornell.core.entity.ActomEntries; import kornell.core.entity.EnrollmentEntries; import kornell.core.entity.EnrollmentsEntries; import kornell.core.util.StringUtils; import kornell.gui.client.event.ActomEnteredEvent; import kornell.gui.client.event.ActomEnteredEventHandler; import kornell.gui.client.event.NavigationAuthorizationEvent; import kornell.gui.client.event.ProgressEvent; import kornell.gui.client.event.ProgressEventHandler; import kornell.gui.client.sequence.NavigationRequest; public class SCORM12Runtime implements ActomEnteredEventHandler, ProgressEventHandler { private static final Logger logger = Logger.getLogger(SCORM12Runtime.class.getName()); private static SCORM12Runtime instance; private EnrollmentsEntries entries; private SCORM12Adapter currentAPI = null; private KornellSession session; private PlaceController placeCtrl; private Map<String,CMITree> forestCache = new HashMap<>(); private EventBus bus; private boolean disableNextButton; private boolean disablePrevButton; private Timer disableButtonsTimer; private SCORM12Runtime(EventBus bus, KornellSession session, PlaceController placeCtrl, EnrollmentsEntries entries){ this.entries = entries; this.session = session; this.placeCtrl = placeCtrl; this.bus = bus; bus.addHandler(ActomEnteredEvent.TYPE, this); bus.addHandler(ProgressEvent.TYPE, this); initializeDisableButtonsTimer(); } public static synchronized SCORM12Runtime launch(EventBus bus, KornellSession session, PlaceController placeCtrl,EnrollmentsEntries entries){ instance = new SCORM12Runtime(bus, session, placeCtrl, entries); return instance; } @Override public void onActomEntered(ActomEnteredEvent event) { logger.info("Loading [enrollmentUUID:"+event.getEnrollmentUUID()+"][actomKey:"+event.getActomKey()+"]"); if (currentAPI != null) currentAPI.onActomEntered(); bindNewAdapter(event.getEnrollmentUUID(),event.getActomKey()); } private void bindNewAdapter(String enrollmentUUID, String actomKey) { ActomEntries actomEntries = lookupActomEntries(enrollmentUUID, actomKey); SCORM12Adapter apiAdapter = SCORM12Adapter.create(this,session,placeCtrl,enrollmentUUID,actomKey,actomEntries); SCORM12Binder.bindToWindow(apiAdapter); } private ActomEntries lookupActomEntries(String enrollmentUUID, String actomKey) { Map<String, EnrollmentEntries> enrollmentEntriesMap = entries.getEnrollmentEntriesMap(); EnrollmentEntries enrollmentEntries = enrollmentEntriesMap.get(enrollmentUUID); if(enrollmentEntries != null){ Map<String, ActomEntries> actomEntriesMap = enrollmentEntries.getActomEntriesMap(); ActomEntries actomEntries = actomEntriesMap.get(actomKey); return actomEntries; } else { logger.warning("Enrollment entries not found for ["+enrollmentUUID+"]["+actomKey+"]"); logger.warning("Current enrollments: "); Set<String> enrollments = entries.getEnrollmentEntriesMap().keySet(); for (String enroll : enrollments) { logger.warning("- "+enroll); } return null; } } public CMITree getDataModel(String targetUUID,String actomKey) { //trim query params when building cache key int index = actomKey.indexOf("?"); if (index != -1) { actomKey= actomKey.substring(0 , index); } String cacheKey = StringUtils.hash(targetUUID,actomKey); CMITree dataModel = forestCache.get(cacheKey); if (dataModel == null){ ActomEntries ae = lookupActomEntries(targetUUID,actomKey); if(ae != null){ dataModel = CMITree.create(ae.getEntries()); } else { logger.warning("DataModel not found for ["+targetUUID+"]["+actomKey+"]"); dataModel = CMITree.create(new HashMap<String,String>()); } } forestCache.put(cacheKey, dataModel); return dataModel; } public void onLMSSetValue(String key, String value) { if ("knl.next".equals(key)){ bus.fireEvent(NavigationRequest.next()); } else if ("knl.prev".equals(key)){ bus.fireEvent(NavigationRequest.prev()); } else if (key != null && key.endsWith(".nextEnabled")){ boolean isOk = "true".equals(value); disableNextButton = !isOk; bus.fireEvent(NavigationAuthorizationEvent.next(isOk)); } else if (key != null && key.endsWith(".prevEnabled")){ boolean isOk = "true".equals(value); disablePrevButton = !isOk; bus.fireEvent(NavigationAuthorizationEvent.prev(isOk)); } } private void initializeDisableButtonsTimer(){ bus.fireEvent(NavigationAuthorizationEvent.next(false)); bus.fireEvent(NavigationAuthorizationEvent.prev(false)); disableButtonsTimer = new Timer() { public void run() { bus.fireEvent(NavigationAuthorizationEvent.next(!disableNextButton)); bus.fireEvent(NavigationAuthorizationEvent.prev(!disablePrevButton)); } }; // Schedule the timer to run after 3s disableButtonsTimer.schedule(3000); } @Override public void onProgress(ProgressEvent event) { disableNextButton = false; disablePrevButton = false; initializeDisableButtonsTimer(); } }