2 * SCORM-1.2 API-Adapter Java Applet for ATutor
3 * Copyright (c) Matthai Kurian
5 * Made for ATutor, the same license terms as for ATutor itself apply.
7 * This Applet handles communication between ATutor and SCORM-1.2
8 * Sharable Content Objects (SCOs). Most communication is via Liveconnect.
9 * CMI (Computer Managed Instruction) data is sent to ATutor through http POST
10 * to an ATutor server side PHP script. SCORM-1.2 runtime behavior and CMI
11 * datamodel management is done by the PfPLMS SCORM-1.2 API-Adapter Core.
14 import java.util.Hashtable;
15 import java.util.Enumeration;
19 public class ATutorApiAdapterApplet
20 extends java.applet.Applet
21 implements ch.ethz.pfplms.scorm.api.ApiAdapterInterface
23 private ch.ethz.pfplms.scorm.api.ApiAdapter core;
25 private Hashtable ATutorScoCmi = new Hashtable();
27 private String ATutorStudentId;
28 private String ATutorStudentName;
30 private String ATutorScoId;
31 private String ATutorPreparedScoId;
33 private boolean isVerbose = false;
35 public ATutorApiAdapterApplet () {
36 core = new ch.ethz.pfplms.scorm.api.ApiAdapter ();
39 public final void init () {
40 if (getParameter("verbose") != null) isVerbose = true;
41 ATutorStudentId = getParameter ("student_id");
42 ATutorStudentName = getParameter ("student_name");
43 say ("cmi.core.student_id=" +ATutorStudentId);
44 say ("cmi.core.student_name=" +ATutorStudentName);
47 private final void say (String s) {
48 if (isVerbose) System.out.println (s);
51 private final static String decode (String es) {
53 String s = es.replace('+', ' ');
58 StringBuffer rv = new StringBuffer(l);
63 while ((i = s.indexOf('%', a)) >= 0) {
64 rv.append(s.substring(a, i));
67 while (i+2 < l && s.charAt(i) == '%') i+=3;
69 if (b == null || b.length < (i-a)/3) {
70 b = new byte[((i-a)/3)];
75 b[x++] = (byte) Integer.parseInt(
76 s.substring(a+1, a+3), 16
79 rv.append(new String(b, 0, x, "utf-8"));
82 if (a < l) rv.append(s.substring(a));
85 } catch (Exception e) {
91 * Methods for ATutor to call via Liveconnect
94 public final void ATutorPrepare (String sco_id) {
97 StringBuffer P = new StringBuffer();
98 P.append ("&sco_id="+sco_id);
99 say ("Retreiving cmi for sco="+sco_id+" from ATutor server");
101 //po = (HttpURLConnection) ( new java.net.URL (
102 po = (URLConnection) ( new java.net.URL (
103 getCodeBase().toString() + "read.php"
106 po.setRequestProperty (
108 "application/x-www-form-urlencoded"
110 po.setRequestProperty (
112 Integer.toString (P.length())
114 po.setDoOutput (true);
115 po.setUseCaches (false);
116 //po.setRequestMethod ("POST");
117 po.setAllowUserInteraction (false);
119 OutputStream os = po.getOutputStream();
120 os.write (P.toString().getBytes());
124 BufferedReader br = new BufferedReader(
125 new InputStreamReader(
130 while ((s=br.readLine())!=null) {
131 if (s.indexOf('=') == -1) continue;
132 l = s.substring (0, s.indexOf('='));
133 r = s.substring (s.indexOf('=')+1, s.length());
136 ATutorScoCmi.put (l,r);
138 } catch (Exception e) {
139 say ("ATutor cmi retrieval failed.");
142 ATutorPreparedScoId = sco_id;
143 say ("Done. Note: this was cmi for the next sco ("+sco_id+") to launch.");
146 public final void ATutorReset (String s) {
147 if (s != null && s.equals(ATutorScoId)) {
150 say ("Reset by ATutor client.");
154 private final String ATutorCommit (boolean fin) {
156 if (ATutorScoId == null) return "false";
159 StringBuffer P = new StringBuffer();
160 Hashtable ins = core.getTransNew ();
161 Hashtable mod = core.getTransMod ();
163 Object o = core.sysGet ("cmi.core.entry");
164 if (o != null && o.toString().equals ("ab-initio")) {
165 mod.put ("cmi.core.entry", "");
171 P.append ("&sco_id=" +ATutorScoId);
174 for (Enumeration e = ins.keys(); e.hasMoreElements(); i++) {
175 Object l = e.nextElement();
176 Object r = ins.get(l);
177 P.append("&iL["+i+"]="+l.toString());
178 P.append("&iR["+i+"]="+URLEncoder.encode(r.toString()));
182 for (Enumeration e = mod.keys(); e.hasMoreElements(); u++) {
183 Object l = e.nextElement();
184 Object r = mod.get(l);
185 P.append("&uL["+u+"]="+l.toString());
186 P.append("&uR["+u+"]="+URLEncoder.encode(r.toString()));
189 if (i == 0 && u == 0) {
190 say ("Nothing to commit.");
194 //HttpURLConnection po;
198 //po = (HttpURLConnection) ( new java.net.URL (
199 po = (URLConnection) ( new java.net.URL (
200 getCodeBase().toString()
204 po.setRequestProperty (
206 "application/x-www-form-urlencoded"
208 po.setRequestProperty (
210 Integer.toString (P.length())
212 po.setDoOutput (true);
213 po.setUseCaches (false);
214 //po.setRequestMethod ("POST");
215 po.setAllowUserInteraction (false);
217 OutputStream os = po.getOutputStream();
218 os.write (P.toString().getBytes());
222 BufferedReader r = new BufferedReader(
223 new InputStreamReader(
229 while ((s=r.readLine())!=null) {
232 } catch (EOFException ok) {}
235 } catch (Exception e) {
236 say ("ATutor cmi storage failed.");
242 public final String ATutorGetValue (String l) {
243 String rv = core.LMSGetValue (l);
244 say ("ATutorGetValue("+l+")="+rv);
249 * Liveconnect interface methods for SCO
252 public final String LMSInitialize (String s) {
253 String rv = core.LMSInitialize(s);
254 say ("LMSInitialize("+s+")="+rv);
255 if (rv.equals("false")) return rv;
257 rv = core.LMSInitialize(s);
258 ATutorScoId = ATutorPreparedScoId;
259 core.sysPut ("cmi.core.student_id", ATutorStudentId);
260 core.sysPut ("cmi.core.student_name", ATutorStudentName);
261 core.sysPut (ATutorScoCmi);
266 public final String LMSCommit (String s) {
267 String rv = core.LMSCommit(s);
268 if (rv.equals("false")) return rv;
269 rv = ATutorCommit(false);
270 say ("LMSCommit("+s+")="+rv);
274 public final String LMSFinish (String s) {
275 String rv = core.LMSFinish(s);
276 say ("LMSFinish("+s+")="+rv);
277 if (rv.equals("false")) return rv;
278 rv = ATutorCommit(true);
284 public final String LMSGetDiagnostic (String e) {
285 String rv = core.LMSGetDiagnostic (e);
286 say ("LMSGetDiagnostic("+e+")="+rv);
290 public final String LMSGetErrorString (String e) {
291 String rv = core.LMSGetErrorString (e);
292 say ("LMSGetErrorString("+e+")="+rv);
296 public final String LMSGetLastError () {
297 String rv = core.LMSGetLastError ();
298 say ("LMSLastError()="+rv);
302 public final String LMSGetValue (String l) {
303 String rv = core.LMSGetValue (l);
304 say ("LMSGetValue("+l+")="+rv);
308 public final String LMSSetValue (String l, String r) {
309 String rv = core.LMSSetValue (l, r);
310 say ("LMSSetValue("+l+"="+r+")="+rv);