package kornell.scorm.client.scorm12; import static kornell.core.util.StringUtils.isSome; import static kornell.scorm.client.scorm12.Scorm12.logger; import com.google.gwt.core.shared.GWT; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.Timer; import kornell.api.client.Callback; import kornell.api.client.KornellSession; import kornell.core.entity.ActomEntries; import kornell.core.entity.ContentSpec; import kornell.gui.client.presentation.classroom.ClassroomPlace; public class SCORM12Adapter implements CMIConstants { /** * How much time a client can stay unsynced with the server after setting a * data model value, in milliseconds. */ private static final int DIRTY_TOLERANCE = 2000; public static SCORM12Adapter create(SCORM12Runtime rte, KornellSession session, PlaceController placeCtrl, String enrollmentUUID, String actomKey, ActomEntries entries) { return new SCORM12Adapter(rte, session, placeCtrl, enrollmentUUID, actomKey, entries); } // Scope Parameters private String enrollmentUUID; private String actomKey; // State private String lastError = NoError; // UI/Client private KornellSession client; private PlaceController placeCtrl; private SCORM12Runtime rte; private Timer timer; public SCORM12Adapter(SCORM12Runtime rte, KornellSession session, PlaceController placeCtrl, String enrollmentUUID, String actomKey, ActomEntries ae) { logger.info("SCORM API 1.2.2015_05_07_20_00"); this.rte = rte; this.enrollmentUUID = enrollmentUUID; this.actomKey = actomKey; this.client = session; this.placeCtrl = placeCtrl; } public String LMSInitialize(String param) { String result = TRUE; logger.finer("LMSInitialize[" + param + "] = " + result); return result; } public String LMSFinish(String param) { String result = TRUE; logger.finer("LMSFinish[" + param + "]"); return result; } public String LMSGetLastError() { logger.finer("LMSGetLastError[]"); return lastError; } public String LMSGetValue(String param, String moduleUUID) { String targetUUID = getEnrollmentUUID(moduleUUID); CMITree dataModel = getDataModel(targetUUID,actomKey); String result = ""; if (dataModel != null) result = dataModel.getValue(param); else logger.warning("Null data model for LMSGetValue[" + param + "]@[" + moduleUUID + "/"+actomKey+"]"); logger.finer("LMSGetValue[" + param + "]@[" + moduleUUID + "/"+actomKey+"] = "+ result); return result; } public String LMSCommit(String param) { String result = TRUE; syncOnLMSCommit(); logger.finer("LMSCommit[" + param + "] = " + result); return result; } private void syncOnLMSCommit() { scheduleSync(enrollmentUUID,actomKey,"syncOnLMSCommit"); } public String LMSSetDouble(String key, Double value, String moduleUUID) { String strValue = Double.toString(value); return LMSSetString(key, strValue,moduleUUID); } //TODO: Consider API changes for MultiSCO public String LMSSetString(String key, String value,String moduleUUID) { String result = FALSE; String targetUUID = getEnrollmentUUID(moduleUUID); CMITree dataModel = getDataModel(targetUUID,actomKey); if(dataModel != null){ result = dataModel.setValue(key, value); rte.onLMSSetValue(key,value); } else logger.warning("Null data model for LMSSetValue [" + key + " = " + value+ "]@[" + targetUUID + "/"+actomKey+"] = " + result); scheduleSync(targetUUID,actomKey); logger.finer("LMSSetValue [" + key + " = " + value+ "]@[" + targetUUID + "/"+actomKey+"] = " + result); return result; } private CMITree getDataModel(String moduleUUID, String moduleActomKey) { String targetUUID = getEnrollmentUUID(moduleUUID); CMITree dataModel = rte.getDataModel(targetUUID,moduleActomKey); return dataModel; } private String getEnrollmentUUID(String moduleUUID) { return isSome(moduleUUID) ? moduleUUID : enrollmentUUID; } public void launch(String enrollmentUUID) { placeCtrl.goTo(new ClassroomPlace(enrollmentUUID,ContentSpec.SCORM12)); } private void scheduleSync(final String moduleUUID, final String moduleActomKey) { scheduleSync(moduleUUID,moduleActomKey,"scheduledSync"); } private void scheduleSync(final String moduleUUID, final String moduleActomKey, final String syncCause) { if (timer == null) timer = new Timer() { public void run() { syncAfterSet(moduleUUID,moduleActomKey); } private void syncAfterSet(String moduleUUID,String moduleActomKey) { //GWT.log("Sync Scheduled: cause["+syncCause+"] - key["+actomKey+"]"); sync(moduleUUID,moduleActomKey,syncCause); timer=null; } }; timer.schedule(DIRTY_TOLERANCE); } public void onActomEntered() { scheduleSync(enrollmentUUID,actomKey,"onActomEntered"); } private void sync(final String syncEnrollmentUUID,final String syncActomKey, final String syncCause) { class Scrub extends Callback<ActomEntries> { @Override public void ok(ActomEntries to) { // TODO: Scrub only verified getDataModel(syncEnrollmentUUID,syncActomKey).scrub(); } } CMITree dataModel = getDataModel(syncEnrollmentUUID,syncActomKey); boolean isDirty = dataModel.isDirty(); if (dataModel != null && isDirty) { //GWT.debugger(); client.enrollment(syncEnrollmentUUID) .actom(syncActomKey) .put(CMITree.collectDirty(dataModel), syncCause, new Scrub()); } } }