Index: openacs-4/packages/lorsm/lorsm.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/lorsm.info,v diff -u -N -r1.12 -r1.13 --- openacs-4/packages/lorsm/lorsm.info 17 May 2007 12:24:54 -0000 1.12 +++ openacs-4/packages/lorsm/lorsm.info 13 Aug 2007 09:20:14 -0000 1.13 @@ -7,13 +7,13 @@ f f - + Ernie Ghiglione Application to manage the services from the Learning Object Repository. - 2005-05-26 + 2007-07-17 This application manages the services from the Learning Object Repository: upload courses, manage and create metadata, delete resources and courses. - + Index: openacs-4/packages/lorsm/lib/user-lorsm.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/lib/user-lorsm.tcl,v diff -u -N -r1.18 -r1.19 --- openacs-4/packages/lorsm/lib/user-lorsm.tcl 19 Apr 2007 19:44:22 -0000 1.18 +++ openacs-4/packages/lorsm/lib/user-lorsm.tcl 13 Aug 2007 09:20:14 -0000 1.19 @@ -20,6 +20,7 @@ set lors_central_package_id [apm_package_id_from_key "lors-central"] set lors_central_url [apm_package_url_from_id $lors_central_package_id] + set elements_list { course_name { label "[_ lorsm.Course_Name_1]" @@ -36,26 +37,45 @@ } html { width 70% } } +} + +if { [empty_string_p $community_id] } { + append elements_list { subject { label "[_ lorsm.Subject]" display_eval {[dotlrn_community::get_community_name $community_id]} html { align center width 20% } link_url_eval {[dotlrn_community::get_community_url $community_id]} link_html {title "[_ lorsm.Access_Course]"} } + } +} + +append elements_list { last_viewed { label "[_ lorsm.Last_Viewed_On]" html { align center width 10% } display_eval {[lc_time_fmt $last_viewed "%x"]} } + viewed_percent { label "[_ lorsm._Viewed]" html { align right } display_eval {[lc_numeric $viewed_percent "%.2f"]} } + + lesson_status { + label "Completed" + html { align center } + display_template { + @d_courses.lesson_status;noquote@ + } + } } +#label "[_ lorsm._CourseStatus]" + if { ![string equal $lors_central_package_id 0] && ![empty_string_p $community_id] } { if { [lors_central::check_inst -user_id $user_id -community_id $community_id] } { append elements_list " @@ -88,32 +108,36 @@ if {![empty_string_p $community_id]} { set extra_query "and cpmc.community_id = :community_id" } + foreach package $package_id { - db_multirow -extend { admin_p item_id ims_md_id last_viewed total_item_count viewed_item_count viewed_percent course_url } -append d_courses select_d_courses { } { + db_multirow -extend { admin_p item_id ims_md_id last_viewed total_item_count viewed_item_count viewed_percent course_url lesson_status } -append d_courses select_d_courses { } { set ims_md_id $man_id + if { [string eq $format_name "default"] } { # micheles set context [site_node::get_url_from_object_id -object_id $lorsm_instance_id] if ([db_0or1row query " select - cpr.man_id, - cpr.res_id, + cp.man_id, case when upper(scorm_type) = 'SCO' then 'delivery-scorm' else 'delivery' end as needscorte from - ims_cp_resources cpr + ims_cp_manifests cp left join (select man_id, max(scorm_type) as scorm_type from ims_cp_resources group by man_id ) as cpr using (man_id) where - cpr.man_id = :man_id - order by cpr.scorm_type desc limit 1" + cp.man_id = :man_id " ]) { - ns_log Debug "lorsm - $needscorte" set delivery_method delivery - set course_url_url [export_vars -base "[lindex $context 0]$delivery_method" -url {man_id}] + set course_url_url [export_vars -base "[lindex $context 0]$delivery_method/" -url {man_id}] + #this popup shouldn't affect delivery should popup blocker be in place + if { [string eq $needscorte "delivery-scorm"] } { + set course_url "> $course_name" + } else { set course_url "$course_name" + } ns_log Debug "lorsm - course_url: $course_url" } else { set course_url "NO RESOURCES ERROR" @@ -122,8 +146,78 @@ set course_url "$course_name" } + #LET's CHECK IF delivery is RTE, so there should be some tracking. + #the code, differentely than above, check the delivery method as per above + + # Get the course name + if {[db_0or1row manifest " + select + cp.course_name, + cp.fs_package_id, + isscorm, + pf.folder_name, + pf.format_name, + case + when upper(scorm_type) = 'SCO' then 'delivery-scorm' + else 'delivery' + end as deliverymethod + from + ims_cp_manifests cp left join (select man_id, max(scorm_type) as scorm_type from ims_cp_resources group by man_id ) as cpr using (man_id) , + lorsm_course_presentation_formats pf + where + cp.man_id = :man_id + and cp.parent_man_id = 0 + and cp.course_presentation_format = pf.format_id "]} { + # Course Name + if {[empty_string_p $course_name]} { + set course_name "No Course Name" + } + } else { + set course_name "No Course Name" + } + + set lesson_status "N/A" + + if { [string equal $deliverymethod "delivery-scorm"] } { + set icon "" + if { ! [ db_0or1row isanysuspendedsession "select lorsm.track_id as track_id, + cmi.lesson_status as lesson_status from + lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $man_id + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $man_id + and + cmi.item_id = $man_id + order by + lorsm.track_id desc + limit 1" ] } { + #item has no track for the user + #the icon should be the same as per "not yet visited" + append icon "\"Not" + } else { + switch -regexp $lesson_status { + null { append icon "\"Not" } + incomplete { append icon "\"Incomplete\"" } + complete { append icon "\"Completed\"" } + failed { append icon "\"Failed\"" } + "not attempted" { append icon "\"Not" } + passed { append icon "\"Passed\"" } + default { append icon " $lesson_status ** \"$lesson_status\""} + } + } + set lesson_status $icon + } + # DEDS: these are expensive # and for demo purposes only + db_0or1row get_last_viewed { } set all_items [db_list get_total_items { }] set total_item_count [llength $all_items] Index: openacs-4/packages/lorsm/sql/postgresql/lorsm-cmi-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/sql/postgresql/lorsm-cmi-create.sql,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/lorsm/sql/postgresql/lorsm-cmi-create.sql 26 May 2005 18:14:59 -0000 1.1 +++ openacs-4/packages/lorsm/sql/postgresql/lorsm-cmi-create.sql 13 Aug 2007 09:20:14 -0000 1.2 @@ -59,7 +59,7 @@ constraint lorsm_cmi_core_man_id_fk foreign key (man_id) references ims_cp_manifests (man_id), constraint lorsm_cmi_core_item_id_fk foreign key - (item_id) references ims_cp_items(ims_item_id) + (item_id) references acs_objects (object_id) ); create index lorsm_cmi_core__stud_id_idx on lorsm_cmi_core (student_id); @@ -212,7 +212,7 @@ on delete cascade, student_id varchar(100), mastery_score varchar(10), -- not mandatory, gettable, not settable - max_time_allowed character varying(12), -- mandatory, not gettable, settable + max_time_allowed character varying(14), -- mandatory, not gettable, settable time_limit_action varchar(100) -- not mandatory, gettable, not settable ); Index: openacs-4/packages/lorsm/sql/postgresql/upgrade/upgrade-0.8d-0.8d2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/sql/postgresql/upgrade/upgrade-0.8d-0.8d2.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/sql/postgresql/upgrade/upgrade-0.8d-0.8d2.sql 13 Aug 2007 09:20:14 -0000 1.2 @@ -0,0 +1,10 @@ +-- making column larger +ALTER TABLE lorsm_cmi_core DROP CONSTRAINT lorsm_cmi_core_item_id_fk; + +-- making constraint less restrictive +ALTER TABLE lorsm_cmi_core + ADD CONSTRAINT lorsm_cmi_core_item_id_fk FOREIGN KEY (item_id) + REFERENCES acs_objects (object_id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE lorsm_cmi_student_data ALTER max_time_allowed TYPE character varying(14); Index: openacs-4/packages/lorsm/src/java/.classpath =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/.classpath,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/.classpath 13 Aug 2007 09:20:14 -0000 1.2 @@ -0,0 +1,9 @@ + + + + + + + + + Index: openacs-4/packages/lorsm/src/java/.project =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/.project,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/.project 13 Aug 2007 09:20:14 -0000 1.2 @@ -0,0 +1,17 @@ + + + dotlrnscormapplet + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Index: openacs-4/packages/lorsm/src/java/descriptionforjar.jardesc =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/descriptionforjar.jardesc,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/descriptionforjar.jardesc 13 Aug 2007 09:20:14 -0000 1.2 @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + Index: openacs-4/packages/lorsm/src/java/java.policy.applet =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/java.policy.applet,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/java.policy.applet 13 Aug 2007 09:20:14 -0000 1.2 @@ -0,0 +1,7 @@ +/* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/ +/* DO NOT EDIT */ + +grant { + permission java.security.AllPermission; +}; + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelInterface.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelInterface.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelInterface.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,246 @@ +/******************************************************************************* +** +** Filename: DataModelInterface.java +** +** File Description: The DataModelInterface class acts as an interface +** between the LMS API and the CMI Data Model itself. +** The API will invoke methods on the Data Model Interface +** for LMSGetValue() and LMSSetValue() request. +** +** The Data Model Interface then will interact with the +** SCO Data Manager to process the appropriate request. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 263: Removal of reference to version of +** SCORM. +** +** 01/12/2001 S. Thropp PT 377: Changed all occurrences of AU/au to +** SCO/sco. +** +*******************************************************************************/ +package org.adl.datamodels; + +//native java imports +import java.io.*; +import java.util.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.cmi.*; + +public class DataModelInterface +{ + + /**************************************************************************** + ** + ** Method: DataModelInterface() + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ***************************************************************************/ + public DataModelInterface() + {} + + /**************************************************************************** + ** + ** Method: processGet + ** Input: String theRequest - The LMSGetValue() request from the SCO + ** SCODataManager - The SCO Data Manager that holds all of the + ** data/data structure for the SCO + ** + ** Output: String - the value of the Data model element requested + ** + ** Description: This method begins the processing of an LMSGetValue() + ** request. The method first creates a CMIRequest object. This + ** object is responsible for tokenizing the requested string. The + ** method then invokes the getValue() method on the SCO Data Manager + ** and returns the associated result. + ** + ***************************************************************************/ + public String processGet(String theRequest, + SCODataManager scoData, + DMErrorManager dmErrMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println(""); + System.out.println("**********************************"); + System.out.println("In DataModelInterface::processGet()"); + System.out.println("**********************************"); + System.out.println(""); + } + // Variable to hold the result from the LMSGetValue() + String result = new String(""); + + if ( DebugIndicator.ON ) + { + System.out.println("In DataModelInterface::processGet"); + } + + if ( isValidRequest(theRequest) == true ) + { + // Create a CMI Request object + CMIRequest request = new CMIRequest(theRequest,true); + + // Process the requst + result = scoData.getValue(request, + dmErrMgr); + } + else + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() or LMSSetValue() + System.out.println("Data model not supported by SCORM"); + } + + // Notify error manager + dmErrMgr.SetCurrentErrorCode("201"); + } + + if ( DebugIndicator.ON ) + { + System.out.println(""); + System.out.println("**********************************"); + System.out.println("Returning to API: [" + result + "]"); + System.out.println("**********************************"); + System.out.println(""); + } + return result; + } + + /**************************************************************************** + ** + ** Method: processSet + ** Input: String theRequest - The LMSGetValue() request from the SCO + ** SCODataManager - The SCO Data Manager that holds all of the + ** data/data structure for the SCO + ** LMSErrorManager - Error manager used for error reporting + ** + ** Output: none + ** + ** Description: This method begins the processing of an LMSSetValue() + ** request. The method first creates a CMIRequest object. This + ** object is responsible for tokenizing the requested string. The + ** method then invokes the setValue() method on the SCO Data Manager + ** + ***************************************************************************/ + public void processSet(String theRequest, + SCODataManager scoData, + DMErrorManager dmErrMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println(""); + System.out.println("***********************************"); + System.out.println("In DataModelInterface::processSet()"); + System.out.println("***********************************"); + System.out.println(""); + } + + StringTokenizer stk = new StringTokenizer(theRequest, ",", false); + String tmpRequest = stk.nextToken(); + + if ( isValidRequest(tmpRequest) == true ) + { + // Create a CMI Request object + CMIRequest request = new CMIRequest(theRequest,false); + + // Process the requst + scoData.setValue(request, + dmErrMgr); + } + else + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() or LMSSetValue() + System.out.println("Data model not supported by SCORM"); + } + + // Notify error manager + dmErrMgr.SetCurrentErrorCode("201"); + } + } // end of processSet + + /**************************************************************************** + ** + ** Method: isValidRequest + ** Input: String request - the request from the SCO + ** Output: Boolean value stating whether the request is valid + ** + ** Description: This method checks to see if the request received is + ** valid. The request must have at lease 2 tokens in order to + ** be valid (i.e. cmi.suspend_data) + ** + ***************************************************************************/ + private boolean isValidRequest(String theRequest) + { + boolean rtrnFlag = true; + StringTokenizer stk = new StringTokenizer(theRequest, ".", false); + int totalNumOfTok = stk.countTokens(); + + // The request must have at least 2 tokens. If a request has less + // than two tokens then there was an invalid request received + if ( totalNumOfTok < 2 ) + { + rtrnFlag = false; + } + + String token = stk.nextToken(); + // Check to make sure SCO is using the cmi data model + if ( token.equals("cmi") ) + { + rtrnFlag = true; + } + else + { + rtrnFlag = false; + } + + return rtrnFlag; + + } // end of isValidRequest() + +} // end of DataModelInterface Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelValidator.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelValidator.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/DataModelValidator.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,928 @@ +/******************************************************************************* +** +** Filename: DataModelValidator.java +** +** File Description: This class acts as a Data Model element verifier. It +** is used to verify that the set value of an LMSSetValue() +** request maps to the correct type of the element. It +** is also used to verify that a return value from an LMS +** for an LMSGetValue() request maps to the correct type +** expected. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/05/2000 ADLI Project PT110 : The method checkString256() was +** changed to checkString255() to +** reflect the CMI 3.0.3 changes +** +** 09/07/2000 ADLI Project PT112 : The method checkLocale() was removed +** due to data model changes. CMILocale +** elements now fall under the +** CMIString255 category. +** +** 11/07/2000 ADLI Project PT 297: Vocabulary lists and data types were +** updated to match the SCORM 1.1 +** specifications. +** +** 11/15/2000 S. Thropp PT 263: Removal of reference to SCORM +** version. +** PT 297: Cleaned up definition of Time and +** Timespan. The seconds for these two data +** types must be in the following format: +** SS.SS - five chars +** +** 12/15/2000 J. Poltrack PT 297: The credit vocab member "no credit" +** was changed to "no-credit" +** +** 12/27/2001 Jeff Falls Added checkScorDecimal() to test the +** "cmi.core.score" elements for negative +** values +** +** 01/21/2001 Jeff Falls Added check to checkScoreDecimal() to test +** for normalized scores (0 <= n >= 100) +** +** 05/09/2002 S. Thropp PT1828: Removed the convertString() function +** This function is not used and it is private. +** Also removed fixWord function, this again +** is a private function that was only used +** by the convertString function. +** +** 05/09/2002 S. Thropp PT1832: The checkIdentifier method returns +** true for blank identifiers. This is not +** correct according to the SCORM. Added +** test to see if the identifier is blank +** +** 05/09/2002 S. Thropp PT1833: Changed checkTime to correctly +** check the seconds part. Code added to make +** sure seconds has at least 2 decimals +** (03:00:03 vs. 03:00:3) +** +** 05/14/2002 B. Capone PT1833: Modified the hours/minutes if +** statement in the try block of checkTime(). +** Only want to check seconds if hours and +** minutes are within allowable range. +** +********************************************************************************/ +package org.adl.datamodels; + +//native java imports +import java.io.*; +import java.util.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.cmi.*; + +public class DataModelValidator implements Serializable +{ + // Hash table to hold the different vocabulary types found in the SCORM + private static transient Hashtable vocabulary; + + /**************************************************************************** + ** + ** Method: DataModelvalidator + ** Input : none + ** Output: none + ** + ** Description: Default constructor - Sets up the hash table with the + ** following keys: + ** Mode, Status, Exit, WhyLeft, Credit, Entry, + ** TimeLimitAction, Interaction, and Result. + ** + ** Each key maps to a set of valid values used for the + ** keys vocabulary type + ** + ** Mode - normal,review,browse + ** Status - passed, completed, failed, incomplete, browsed + ** not attempted. + ***************************************************************************/ + public DataModelValidator() + { + vocabulary = new Hashtable(); + + vocabulary.put( "Mode",buildModeList() ); + vocabulary.put( "Status",buildStatusList() ); + vocabulary.put( "Exit",buildExitList() ); + vocabulary.put( "Credit",buildCreditList() ); + vocabulary.put( "Entry",buildEntryList() ); + vocabulary.put( "TimeLimitAction",buildTimeLimitActionList() ); + vocabulary.put( "Interaction",buildInteractionList() ); + vocabulary.put( "Result",buildResultList() ); + } + + /**************************************************************************** + ** + ** Method: buildModeList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Mode vocabulary + ** members: + ** normal,review,browse + ***************************************************************************/ + private String[] buildModeList() + { + int numItems = 3; + String[] list = new String[numItems]; + + list[0] = "normal"; + list[1] = "review"; + list[2] = "browse"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildStatusList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Status vocabulary + ** members: + ** passed,completed,failed,incomplete,browsed,not attempted + ***************************************************************************/ + private String[] buildStatusList() + { + int numItems = 6; + String[] list = new String[numItems]; + + list[0] = "passed"; + list[1] = "completed"; + list[2] = "failed"; + list[3] = "incomplete"; + list[4] = "browsed"; + list[5] = "not attempted"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildExitList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Exit vocabulary + ** members: + ** time-out, suspend, logout + ***************************************************************************/ + private String[] buildExitList() + { + int numItems = 4; + String[] list = new String[numItems]; + + list[0] = ""; + list[1] = "time-out"; + list[2] = "suspend"; + list[3] = "logout"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildCreditList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Credit vocabulary + ** members: + ** credit, no credit + ***************************************************************************/ + private String[] buildCreditList() + { + int numItems = 2; + String[] list = new String[numItems]; + + list[0] = "credit"; + list[1] = "no-credit"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildEntryList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Entry vocabulary + ** members: + ** ab-initio, resume + ***************************************************************************/ + private String[] buildEntryList() + { + int numItems = 3; + String[] list = new String[numItems]; + + list[0] = ""; + list[1] = "ab-initio"; + list[2] = "resume"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildTimeLimitActionList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Time Limit Action + ** vocabulary members: + ** "exit,message", "continue,message", + ** "exit,no message","continue,no message" + ***************************************************************************/ + private String[] buildTimeLimitActionList() + { + int numItems = 5; + String[] list = new String[numItems]; + + list[0] = ""; + list[1] = "exit,message"; + list[2] = "exit,no message"; + list[3] = "continue,message"; + list[4] = "continue,no message"; + return list; + } + + + /**************************************************************************** + ** + ** Method: buildInteractionList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Interaction + ** vocabulary members: + ** true-false, multiple choice, fill in the blank, + ** matching, simple performance, likert, sequencing, + ** numeric + ***************************************************************************/ + private String[] buildInteractionList() + { + int numItems = 8; + String[] list = new String[numItems]; + + list[0] = "true-false"; + list[1] = "choice"; + list[2] = "fill-in"; + list[3] = "matching"; + list[4] = "performance"; + list[5] = "likert"; + list[6] = "sequencing"; + list[7] = "numeric"; + return list; + } + + /**************************************************************************** + ** + ** Method: buildResultList() + ** Input : none + ** Output: String[] - list of members + ** + ** Description: This method builds the list of valid Result + ** vocabulary members: + ** correcct, wrong, unanticipated, neutral, x.x + ***************************************************************************/ + private String[] buildResultList() + { + int numItems = 4; + String[] list = new String[numItems]; + + list[0] = "correct"; + list[1] = "wrong"; + list[2] = "unanticipated"; + list[3] = "neutral"; + + return list; + } + + /**************************************************************************** + ** + ** Method: checkBlank() + ** Input: Element elementToBeChecked - Element to be checked + ** String value - value to be set + ** Output: boolean result - indicates whether or not the value is + ** correct type according to element + ** + ** Description: This method check to see if the value is blank (length + ** of string is 0 + ***************************************************************************/ + public boolean checkBlank(Element elementToBeChecked, + String value) + { + boolean result = false; + if ( value.length() == 0 ) + { + result = true; + } + return result; + } + + /**************************************************************************** + ** + ** Method: checkBoolean() + ** Input: Element elementToBeChecked - Element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the value is + ** correct type according to element + ** + ** Description: This method checks to see if the value passed in + ** is equal to either true or false. + ***************************************************************************/ + public boolean checkBoolean(Element elementToBeChecked, + String value) + { + boolean flag = false; + if ( (value.equals("true")) || + (value.equals("false")) ) + { + flag = true; + } + return flag; + } + + /**************************************************************************** + ** + ** Method: checkFeedback() + ** Input: Element elementToBeChecked - Element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the value is + ** correct type according to element + ** + ** Description: + ***************************************************************************/ + public boolean checkFeedback(Element elementToBeChecked, + String value) + { + return true; + } + + /**************************************************************************** + ** + ** Method: checkString255() + ** Input: Element elementToBeChecked - Element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the value is + ** correct type according to element + ** + ** Description: This method makes sure the value passed in is less + ** than or equal to 255 + ***************************************************************************/ + public boolean checkString255(Element elementToBeChecked, + String value) + { + boolean flag = false; + if ( value.length() <= 255 ) + { + flag = true; + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkString4096() + ** Input: Element elementToBeChecked - Element to be checked + ** String setValue - value to be checked + ** Output: boolean result - indicates whether or not the value is + ** correct type according to element + ** + ** Description: This method checks the value passed in to see if it + ** is less than or equal to 4096 + ***************************************************************************/ + public boolean checkString4096(Element elementToBeChecked, + String value) + { + boolean flag = false; + if ( value.length() <= 4096 ) + { + flag = true; + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkScoreDecimal() + ** Input: Element elementToBeChecked - the element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the value passed in + ** is a valid decimal + ***************************************************************************/ + public boolean checkScoreDecimal(Element elementToBeChecked, + String value) + { + boolean result = false; + + Double zero = new Double(0.0); + Double oneHundred = new Double(100.0); + + if ( !(checkBlank(elementToBeChecked, value)) ) + { + try + { + Double tmpDouble = new Double(value); + + //Check for Normalized Score (0 <= n >= 100) + if ( (tmpDouble.compareTo(zero) >= 0) && + (tmpDouble.compareTo(oneHundred) <= 0) ) + { + result = true; + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println(value + " is not a normalized score"); + System.out.println("0 <= " + value + " >= 100"); + } + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println(value + " is not a valid CMIDecimal Type"); + } + } + + } + else + { + result = true; + } + + return result; + } + + + + /**************************************************************************** + ** + ** Method: checkDecimal() + ** Input: Element elementToBeChecked - the element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the value passed in + ** is a valid decimal + ***************************************************************************/ + public boolean checkDecimal(Element elementToBeChecked, + String value) + { + boolean result = false; + + + if ( !(checkBlank(elementToBeChecked, value)) ) + { + + try + { + Double tmpDouble = new Double(value); + result = true; + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println(value + " is not a valid CMIDecimal Type "); + } + } + } + else + { + result = true; + } + + + return result; + } + + + /**************************************************************************** + ** + ** Method: checkVocabulary + ** Input: Element elementToBeChecked - The element to be checked + ** String value - value to be checked + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the set value passed in + ** is the correct vocabulary member of the element. + ***************************************************************************/ + public boolean checkVocabulary(Element elementToBeChecked, + String value) + { + + boolean flag = false; + String vocabType = elementToBeChecked.getVocabularyType(); + + // find out the field being verified from the element + String[] theList = (String[]) vocabulary.get(vocabType); + + for ( int i = 0; i < theList.length; i++ ) + { + String tmpString = theList[i]; + + if ( (tmpString.equals(value) == true) ) + { + flag = true; + break; + } + } + + + //Check to see if the "Results" category is passing in a decimal number + if ( (vocabType.equals("Result")) && (flag != true) ) + { + flag = checkDecimal(elementToBeChecked, value); + } + + + // No match found + if ( flag == false ) + { + if ( DebugIndicator.ON ) + { + System.out.println("[" + value + "] is not a valid vocabulary member "); + System.out.println("for the " + vocabType + " Vocabulary Type"); + } + } + + return flag; + + } + + /**************************************************************************** + ** + ** Method: checkIdentifier + ** Input: Element elementToBeChecked - element to be checked + ** String value - value to be checked + ** + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method check to make sure the value passed in + ** is a valid identifier. + ***************************************************************************/ + public boolean checkIdentifier(Element elementToBeChecked, + String value) + { + boolean flag = false; + + if ( (value.length() <= 255) && + (value.indexOf(' ') == -1) && + (!(checkBlank(elementToBeChecked,value))) ) + { + flag = true; + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkInteger + ** Input: Element elementToBeChecked - element to be checked + ** String value - value to be checked + ** + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the setValue passed in + ** is a valid integer + ***************************************************************************/ + public boolean checkInteger(Element elementToBeChecked, + String value) + { + boolean flag = false; + + try + { + Integer tmpInt = new Integer(value); + int theValue = tmpInt.intValue(); + + if ( (theValue >= 0) && + (theValue <= 65536) ) + { + flag = true; + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println(value + " has invalid format for an Integer"); + } + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkSInteger() + ** Input: Element elementToBeChecked - element to be checked + ** String value - value to be checked + ** + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure that the value passed + ** in is a valid Signed Integer + ***************************************************************************/ + public boolean checkSInteger(Element elementToBeChecked, + String value) + { + boolean flag = false; + try + { + Integer tmpInt = new Integer(value); + int theValue = tmpInt.intValue(); + + if ( (theValue >= -32768) && + (theValue <= 32768) ) + { + flag = true; + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println(value + " has invalid format for a Signed Integer"); + } + } + + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkTime() + ** Input: Element elementToBeChecked - element to be checked + ** String value - value to be checked + ** + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the value passed in + ** is a valid Time HH:MM:SS.S + ***************************************************************************/ + public boolean checkTime(Element elementToBeChecked, + String value) + { + boolean flag = false; + StringTokenizer stk = new StringTokenizer(value,":",false); + + //Should have 3 tokens: HH, MM, and SS.SS + if ( stk.countTokens() == 3 ) + { + String hour = stk.nextToken(); + String minute = stk.nextToken(); + String sec = stk.nextToken(); + + if ( ( hour.length() == 2 ) && + ( minute.length() == 2) && + ( sec.length() <= 5) ) + { + // Try to convert hours and minutes to integers and seconds to float. + try + { + Integer hourAsInt = new Integer(hour); + Integer minAsInt = new Integer(minute); + + if ( ( (hourAsInt.intValue() >= 0) && + (hourAsInt.intValue() <= 24) ) && + ( (minAsInt.intValue() >= 0) && + (minAsInt.intValue() <= 60) ) ) + { + flag = true; + + // Try to convert seconds. If not, throw NumberFormatException. + // Validate Seconds, SS.SS + // Try to convert seconds. If not, throw NumberFormatException. + StringTokenizer secTokenizer = new StringTokenizer(sec,".",false); + int numTok = secTokenizer.countTokens(); + + String secondsPart = secTokenizer.nextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("secondsPart: " + secondsPart); + } + + if ( secondsPart.length() == 2 ) + { + Double secAsDouble = new Double(secondsPart); + flag = true; + if ( DebugIndicator.ON ) + { + System.out.println("seconds part had 2 chars and a valid decimal"); + } + } + else + { + flag = false; + if ( DebugIndicator.ON ) + { + System.out.println("Seconds Part did not have 2 chars"); + } + } + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Value could not be converted to a time"); + } + + flag = false; + } + } // end if correct size + } // end if correct tokens + + if ( !flag ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Value being used for setting: " + value + + " is not in Valid Time Format (HH:MM:SS.SS)" ); + } + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: checkTimespan() + ** Input: Element elementToBeChecked - element to be checked + ** String value - value to be checked + ** + ** Output: boolean result - indicates whether or not the request is + ** valid + ** + ** Description: This method checks to make sure the value passed in is + ** a valid Timespan HHHH:MM:SS.S + ***************************************************************************/ + public boolean checkTimespan(Element elementToBeChecked, + String value) + { + boolean flag = false; + + if ( !(checkBlank(elementToBeChecked, value)) ) + { + StringTokenizer stk = new StringTokenizer(value,":",false); + + if ( stk.countTokens() == 3 ) + { + String hour = stk.nextToken(); + String minute = stk.nextToken(); + String sec = stk.nextToken(); + + if ( ( (hour.length() >= 2) && (hour.length() <= 4) ) && + (minute.length() == 2) && + (sec.length() <= 5) ) + { + // Check to see if the inputted value can be changed to a "Timespan" + try + { + // Try to convert hours and minutes. If not, throw + // NumberFormatException. + Integer hourAsInt = new Integer(hour); + Integer minAsInt = new Integer(minute); + + + // Make sure hours and minutes are in range + if ( ( (hourAsInt.intValue() >= 0) && + (hourAsInt.intValue() <= 9999) ) && + ( (minAsInt.intValue() >= 0) && + (minAsInt.intValue() <= 99) ) ) + { + flag = true; + } + + // Validate Seconds, SS.SS + // Try to convert seconds. If not, throw NumberFormatException. + StringTokenizer secTokenizer = new StringTokenizer(sec,".",false); + int numTok = secTokenizer.countTokens(); + + String secondsPart = secTokenizer.nextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("secondsPart: " + secondsPart); + } + + if ( secondsPart.length() == 2 ) + { + Double secAsDouble = new Double(secondsPart); + flag = true; + if ( DebugIndicator.ON ) + { + System.out.println("seconds part had 2 chars and a valid decimal"); + } + } + else + { + flag = false; + if ( DebugIndicator.ON ) + { + System.out.println("Seconds Part did not have 2 chars"); + } + } + + // If numTok == 2 then there is a decimal part + if ( numTok == 2 && flag) + { + String decimalPart = secTokenizer.nextToken(); + if ( decimalPart.length() <= 2) + { + Double decAsDouble = new Double(decimalPart); + flag = true; + } + else + { + flag = true; + } + } + + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Value could not be converted to a time"); + } + + // Invalid Date Format + flag = false; + } + } // ends the check for appropriate size + } // Ends if value has 3 tokens + } + else + { + flag = true; + } + + if ( !flag ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Value being used for setting: " + value + + " is not in Valid Time Format (HHHH:MM:SS.SS)" ); + } + } + + return flag; + } + +} // end of DataModelValidator + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/Element.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/Element.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/Element.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,337 @@ +/******************************************************************************* +** +** Filename: Element.java +** +** File Description: The Element class manages the low level detail about +** an CMI element. It holds the value and type of the +** element. It provides methods to determine if the +** element is mandatory,readable,writeable and implemented. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 263: Removal of SCORM version reference +** +*******************************************************************************/ +package org.adl.datamodels; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; + +public class Element implements Serializable +{ + // The value held by the elment + private String value; + + // The type of the element + private String type; + + // Whether or not the element can be set by an AU + private boolean writeable; + + // Whether or not the LMS has implemented the element + private boolean implemented; + + // Whether or not the LMS has initialized the element + // The value attribute will have a value other than + // an empty String ("") + private boolean initialized; + + // Whether or not the element can be seen by an AU + private boolean readable; + + // Whether or not the element is mandatory + private boolean mandatory; + + // The vocabulary type (as needed). Used in verification of valid + // request + private String vocabularyType; + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String inValue - string to set the value attribute + ** String inType - string to set the type attribute + ** boolean writeableFlag - flag indicating if the element is + ** writeable + ** boolean readableFlag - flag indicating if the element is + ** readable + ** boolean mandatoryFlag - flag indicating if the element is + ** mandatory + ** Output: none + ** + ** Description: The Constructor sets up the class and initalizes + ** all of its attributes + ** + ***************************************************************************/ + public Element(String inValue,String inType,String inVocab, + boolean writeableFlag, + boolean readableFlag, + boolean mandatoryFlag) + { + value = inValue; + type = inType; + vocabularyType = inVocab; + writeable = writeableFlag; + readable = readableFlag; + if ( inValue.equalsIgnoreCase("") ) + { + initialized = false; + } + else + { + initialized = true; + } + + mandatory = mandatoryFlag; + implemented = true; + + } // end of constructor + + /**************************************************************************** + ** + ** Method: Default Constructor + ** Input: none + ** Output: none + ** + ** Description: The Default Constructor sets up the class and initalizes + ** all of its attributes to default values + ** + ***************************************************************************/ + public Element() + { + value = new String(""); + type = new String(""); + vocabularyType = new String(""); + writeable = false; + readable = false; + initialized = false; + implemented = false; + mandatory = false; + } // end of Default Constructor + + /**************************************************************************** + ** + ** Method: isWriteable() + ** Input: none + ** Output: boolean result - indicates whether or not the element is + ** writeable + ** + ** Description: Indicates whether or not the element is writeable (can be + ** set with an LMSSetValue() request. + ** + ***************************************************************************/ + public boolean isWriteable() + { + return writeable; + } // end of isWriteable() + + /**************************************************************************** + ** + ** Method: isImplemented + ** Input: none + ** Output: boolean result - indicates whether or not the element is + ** implemented + ** + ** Description: Indicates whether or not the element is implemented. + ** + ***************************************************************************/ + public boolean isImplemented() + { + return implemented; + } // end of isImplemented() + + /**************************************************************************** + ** + ** Method: isInitialized + ** Input: none + ** Output: boolean result - indicates whether or not the element is + ** initialized. + ** + ** Description: Indicates whether or not the element is initialized. + ** + ***************************************************************************/ + public boolean isInitialized() + { + return initialized; + } // end of isInitialized() + + /**************************************************************************** + ** + ** Method: isReadable + ** Input: none + ** Output: boolean result - indicates whether or not the element is + ** readable + ** + ** Description: Indicates whether or not the element is able to be accessed. + ** (accessed via an LMSGetValue(); + ** + ***************************************************************************/ + public boolean isReadable() + { + return readable; + } // end of isReadable() + + /**************************************************************************** + ** + ** Method: isMandatory + ** Input: none + ** Output: boolean result - indicates whether or not the element is + ** mandatory + ** + ** Description: Indicates whether or not the element was mandatory + ** + ***************************************************************************/ + public boolean isMandatory() + { + return mandatory; + } // end of isMandatory() + + /**************************************************************************** + ** + ** Method: getVocabularyType() + ** Input: none + ** Output: String - the specific vocabulary type + ** + ** Description: Returns the vocabulary type of Element. Only those + ** Elements that have a type of CMIVocabulary will have + ** a valid Vocabulary Type. All others will be set to + ** "NULL" + ** + ***************************************************************************/ + public String getVocabularyType() + { + return vocabularyType; + } // end of getVocabularyType() + + /**************************************************************************** + ** + ** Method: getValue + ** Input: none + ** Output: String value - the value of the element + ** + ** Description: Returns the value held by the element. + ** + ***************************************************************************/ + public String getValue() + { + return value; + } // end of getValue() + + /**************************************************************************** + ** + ** Method: setValue + ** Input: String inValue - value to use in setting the element + ** Output: none + ** + ** Description: Sets the elements value determined by the input argument. + ** + ***************************************************************************/ + public void setValue(String inValue) + { + value = inValue; + initialized = true; + } // end of setValue() + + /**************************************************************************** + ** + ** Method: getType + ** Input: none + ** Output: String - the type of the element + ** + ** Description: Returns the type of the element + ** + ***************************************************************************/ + public String getType() + { + return type; + } // end of getType() + + /**************************************************************************** + ** + ** Method: setElement + ** Input: Element - the element to use to set up this element + ** Output: none + ** + ** Description: Sets this object's attributes in accordance with the + ** input element. (Acts like a copy constructor) + ** + ***************************************************************************/ + protected void setElement(Element e) + { + this.type = e.getType(); + this.value = e.getValue(); + this.vocabularyType = e.getVocabularyType(); + this.implemented = e.isImplemented(); + this.initialized = e.isInitialized(); + this.mandatory = e.isMandatory(); + this.readable = e.isReadable(); + this.writeable = e.isWriteable(); + } // end of setElement() + + /**************************************************************************** + ** + ** Method: showElement + ** Input: none + ** Output: none + ** + ** Description: Sends all of the attributes to System.out in a readable + ** manner. + ** + ***************************************************************************/ + public void showElement() + { + if ( DebugIndicator.ON ) + { + System.out.println(" Value " + getValue()); + System.out.println(" Type " + getType()); + System.out.println(" Vocab Type " + getVocabularyType()); + System.out.println(" Writeable " + isWriteable()); + System.out.println(" Readable " + isReadable()); + System.out.println(" Mandatory " + isMandatory()); + System.out.println(" Implemented " + isImplemented()); + System.out.println(" Intialized " + isInitialized()); + } + } // end of showElement() + +} // end of Element + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/SCODataManager.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/SCODataManager.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/SCODataManager.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,511 @@ +/******************************************************************************* +** +** Filename: SCODataManager.java +** +** File Description: This class is responsible for maintaining the Data +** Model content and structure. An SCO Data Manager is created +** with each initialization of an SCO. The SCO Data Manager is +** responsible for any interactions the LMS ,student, or SCO may +** have with the Data Model. +** +** Author: ADLI Technical Team +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java API) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: The CMI_VERSION static attribute is set to +** version 3.4, this is the current version of +** the AICC CMI Data Model. If the version is +** changed, this static attribute should be changed +** accordingly. +** +** The DM_CLASSNAME static attribute is set to +** the fully qualified (package) name for the +** data model classes. The CMI added to the end +** of the string is the prefix to all of the Data +** Model classes. +** +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/07/2000 ADLI Project PT - 264: References to "evaluation", +** "paths", and "student_demographics" were +** removed to reflect SCORM 1.1 changes. +** +** 11/15/2000 S.Thropp PT-290: Added support for new +** cmi.comments_from_lms. +** +** 01/12/2001 S.Thropp PT-377: Changed all occurrences of AU/au +** to SCO/sco. +** +*******************************************************************************/ +package org.adl.datamodels; + +//native java imports +import java.io.*; +import java.util.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.cmi.*; + +public class SCODataManager implements Serializable +{ + // Information required to be furnished by all LMS Systems. What + // all SCOs may depend on upon start up + public CMICore core; + + // Unique information generated by the SCO during + // previous uses, that is needed for the current use + public CMISuspendData suspend_data; + + // Unique information generated at the SCO's creation + // that is needed for every use. + public CMILaunchData launch_data; + + // Comments (from the SCO or Student) about the SCO + public CMIComments comments; + + // Comments (from the LMS or Instructor) about the SCO + public CMICommentsFromLms comments_from_lms; + + // Identifies how the student has performed on individual objectives + // covered by the SCO. + public CMIObjectives objectives; + + // A recognizable and recordable input or group of inputs from the student + // to the computer + public CMIInteractions interactions; + + // Information to support customization of an SCO based + // on a student's performance + public CMIStudentData student_data; + + // Student selected options that are appropriate for subsequent + // SCOs. + public CMIStudentPreference student_preference; + + // The current working Base Category. This could change with each request + // from an SCO + private String workingBaseCategory; + + private static final String CMI_VERSION = "3.4"; + private static final String DM_CLASSNAME = "org.adl.datamodels.cmi.CMI"; + + //*************************************** + //** Accessors to the SCODataManager Data + //*************************************** + public CMICore getCore() + { + return core; + } + public CMISuspendData getSuspendData() + { + return suspend_data; + } + public CMILaunchData getLaunchData() + { + return launch_data; + } + public CMIComments getComments() + { + return comments; + } + + public CMICommentsFromLms getCommentsFromLMS() + { + return comments_from_lms; + } + + public CMIObjectives getObjectives() + { + return objectives; + } + + public CMIInteractions getInteractions() + { + return interactions; + } + public CMIStudentData getStudentData() + { + return student_data; + } + + public CMIStudentPreference getStudentPreference() + { + return student_preference; + } + + //**************************************** + //** Modifiers to the SCODataManager Data + //**************************************** + public void setCore(CMICore inCore) + { + core = inCore; + } + public void setSuspendData(CMISuspendData inSuspendData) + { + suspend_data = inSuspendData; + } + public void setLaunchData(CMILaunchData inLaunchData) + { + launch_data = inLaunchData; + } + public void setComments(CMIComments inComments) + { + comments = inComments; + } + public void setCommentsFromLMS(CMICommentsFromLms inComments) + { + comments_from_lms = inComments; + } + public void setObjectives(CMIObjectives inObjectives) + { + objectives = inObjectives; + } + public void setInteractions(CMIInteractions inInteractions) + { + interactions = inInteractions; + } + public void setStudentData(CMIStudentData inStudentData) + { + student_data = inStudentData; + } + public void setStudentPreference(CMIStudentPreference inStudentPref) + { + student_preference = inStudentPref; + } + + /**************************************************************************** + ** + ** Method: SCODataManager + ** Input: none + ** Output: none + ** + ** Description: Default Constructor + ** + ***************************************************************************/ + public SCODataManager() + { + core = new CMICore(); + suspend_data = new CMISuspendData(); + launch_data = new CMILaunchData(); + comments = new CMIComments(); + comments_from_lms = new CMICommentsFromLms(); + objectives = new CMIObjectives(); + interactions = new CMIInteractions(); + student_data = new CMIStudentData(); + student_preference = new CMIStudentPreference(); + + } // end of default constructor + + /*************************************************************************** + ** + ** Method: getValue + ** Input: CMIRequest theRequest - the current LMSGetValue() request + ** being processed + ** DMErrorManager dmErrorMgr - instance of the Data Model Error + ** manager + ** + ** Output: String - the value of the category requested in the CMI Request + ** + ** Description: This method begins the processing of the LMSGetValue() + ** request. The method invokes the private method + ** processRequest() and returns a string value representing + ** the requested element + ** + ***************************************************************************/ + public String getValue(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if (DebugIndicator.ON) + { + System.out.println("In SCODataManager::getValue"); + } + + // determine the base category + workingBaseCategory = theRequest.getBaseCategory(); + + String result = new String(""); + + if ( workingBaseCategory.equals("_version") ) + { + // set the result to the current version of the CMI Data Model + result = CMI_VERSION; + } + else + { + result = processRequest(theRequest,dmErrorMgr); + } + + return result; + } + + /*************************************************************************** + ** + ** Method: setValue + ** Input: CMIRequest theRequest - the current LMSSetValue() request + ** being processed + ** DMErrorManager dmErrorMgr - instance of the Data Model + ** error manager + ** + ** Output: none + ** + ** Description: This method begins the processing of the LMSSetValue() + ** request. The method invokes the private method + ** processRequest(). + ** + ***************************************************************************/ + public void setValue(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if (DebugIndicator.ON) + { + System.out.println("In SCODataManager::setValue"); + } + // determine the base category + workingBaseCategory = theRequest.getBaseCategory(); + String result = processRequest(theRequest,dmErrorMgr); + return; + } + + /*************************************************************************** + ** + ** Method: processRequest + ** Input: CMIRequest theRequest - the current request being processed + ** DMErrorManager dmErrorMgr - instance of the Data Model + ** error manager + ** + ** Output: String - result - For an LMSGetValue() request the result is + ** the value matching the element requested + ** For an LMSSetValue() request the result is + ** an empty string + ** + ** Description: This method processes both types of request from + ** an SCO (LMSGetValue() and LMSSetValue()). The method + ** uses the Java Reflection API to determine the + ** appropriate method to invoke and which class to invoke + ** the method on. + ** + ***************************************************************************/ + private String processRequest(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + // Result to be returned + String result = new String(""); + + // takes the base category and returns the class name + // (i.e. student_data --> CMIStudentData + String tmpClassName = convertString(workingBaseCategory); + String className = DM_CLASSNAME + tmpClassName; + + if ( DebugIndicator.ON ) + { + System.out.println("Class Name: " + className); + System.out.println("Working Base Cat: " + workingBaseCategory); + } + + try + { + // Find out the Class of the request + Class c = Class.forName(className); + try + { + // Find the field in the SCODataManager that maps + // to the baseCategory + Field tmpField = this.getClass().getField(workingBaseCategory); + + // Set up the array of Class objects + // Each element in the array corresponds to a + // parameter of the method you want to invoke + Class[] parameterTypes = + new Class[] {theRequest.getClass(), dmErrorMgr.getClass()}; + + // Declare a variable to hold the method + Method theMethod; + + // Declare an arry of objects for the arguments to the method + Object[] arguments = new Object[] {theRequest,dmErrorMgr}; + try + { + // Determine the request type + if ( theRequest.isForASetRequest() ) + { + // Find the method on Class c that is represented by the + // name of the method ("performSet") and the parameter + // types + theMethod = c.getMethod("performSet", parameterTypes); + + if ( DebugIndicator.ON ) + { + System.out.println("I will invoke theMethod: " + theMethod); + } + // Invoke the method that was found matching the method name + // and parameter types + theMethod.invoke(tmpField.get(this),arguments); + } + else + { + theMethod = c.getMethod("performGet",parameterTypes); + // Invoke the method that was found matching the method name + // and parameter types + result = + (String) theMethod.invoke(tmpField.get(this),arguments); + } + } + catch ( NoSuchMethodException e ) + { + System.out.println("nosuchmethodexception"); + System.out.println(e); + } + catch ( IllegalAccessException e ) + { + + System.out.println("illegalaccessexception"); + System.out.println(e); + } + catch ( InvocationTargetException e ) + { + System.out.println("InvocationTargetException"); + System.out.println(e); + } + } + catch ( NoSuchFieldException nsfe ) + { + if (DebugIndicator.ON) + { + System.out.println(nsfe); + System.out.println("Error - Data Model Element not Implemented"); + } + dmErrorMgr.recNotImplementedError(theRequest); + } + } + catch ( ClassNotFoundException cnfe ) + { + if (DebugIndicator.ON) + { + System.out.println(cnfe); + System.out.println("Error - Data Model Element not implemented"); + } + dmErrorMgr.recNotImplementedError(theRequest); + } + + return result; + } // end of setValue() + + + /*************************************************************************** + ** + ** Method: convertString + ** Input: String theString - the string that needs converted + ** (i.e. core, student_data). + ** + ** Output: String result - the converted string + ** (i.e. Core, StudentData) + ** + ** Description: The method takes the input string and converts it + ** to the appropriate format. The format is a capital + ** letter followed by the rest of the word, where every + ** other word is capitalized. + ** + ** student_data --> StudentData + ** core --> Core + ***************************************************************************/ + private String convertString(String theString) + { + // Tokenize the base category, using the _ as a separator + StringTokenizer stk = new StringTokenizer(theString, "_", false); + + // Count the total number of tokens + int total = stk.countTokens(); + + // String to hold result + String result = new String(""); + + while ( stk.hasMoreTokens() ) + { + // Invoke the fixWord() method to capitalize the first letter + // and build the rest of the class name + result = result.concat( fixWord( stk.nextToken() ) ); + } + + return result; + } // end of convertString() + + /*************************************************************************** + ** + ** Method: fixWord + ** Input: Strng wordToFix - The word that needs changed into + ** a word meeting our standards + ** + ** Output: String result - The standardized word + ** + ** Description: This method is responsible for standardize the + ** input argument. Standardizing means take the first + ** letter and capitalizing it and then returning + ** the word. + ** + ** (i.e. - student --> Student + ***************************************************************************/ + private String fixWord(String wordToFix) + { + // declare a result string + String result = new String(""); + + // Strip off the first letter + String firstLetter = wordToFix.substring(0,1); + + // save the last part of the word (minus the first letter) + String restOfWord = wordToFix.substring(1); + + // Change the first letter to upper case + String ucFirstLetter = firstLetter.toUpperCase(); + + // Concatenate the first letter with the rest of the word + result = ucFirstLetter.concat(restOfWord); + + // Return the result + return result; + + } // end of fixWord() + +} // end of SCODataManager \ No newline at end of file Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICategory.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICategory.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICategory.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,475 @@ +/******************************************************************************* +** +** Filename: CMICategory.java +** +** File Description: This class represents a CMI Category. This class +** acts as a parent to all of the CMI Data Element +** Categories: +** CMICore, CMIScore, CMISuspendData, CMILaunchData, +** CMIComments, CMIObjectives, CMIObjectiveData, +** CMIEvaluation, CMIEvaluation, CMIEvaluationData, +** CMIInteractions, CMIInteractionData, CMIResponse, +** CMIStudentData, CMIEvaluationComments, CMIAttempt, +** CMITries, CMIStudentDemographics, CMIPath +** and CMIStudentPreference +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S.Thropp PT 291: For performance reasons, remove +** the data model validator as an attribute +** and make it a local variable when needed. +** +** 11/17/2000 S.Thropp PT 292: Changed references to old error +** codes. Codes were changed to map to the +** new error codes. +** +** 01/17/2001 S.Thropp PT 374: Added some more debug statements +** +** 03/20/2002 Bill Capone Added a "SetCurrentErrorCode" to "0" (zero) +** in doSet(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +//import from the applet which controls the writeability +import org.adl.samplerte.client.APIAdapterApplet; + +public class CMICategory implements Serializable +{ + // Indicates whether or not the category can be set by an AU + protected boolean writeable; + + /**************************************************************************** + ** + ** Method: Constructor + ** + ** Input: boolean writeableFlag + ** Output: none + ** + ** Description: Constructs a Data Model Category + ** + ***************************************************************************/ + public CMICategory(boolean writeableFlag) + { + writeable = writeableFlag; + } // end of constructor + + + /**************************************************************************** + ** + ** Method: isWriteable + ** + ** Input: none + ** Output: boolean value stating whether or not the Data Model Category + ** is writeable + ** + ** Description: Returns a boolean value which indicates whether or not + ** the Data Model Element is writeable + ** + ***************************************************************************/ + public boolean isWriteable() + { + return writeable; + } // end of isWriteable() + + /**************************************************************************** + ** + ** Method: determineElementValue + ** Input: Object - the current object (data model category) + ** String - Data Model Element that holds the value that + ** is wanted + ** DMErrorManager - The Data Model Error manager + ** + ** Output: String - the requested value + ** + ** Description: This method determines the value of the input Data model + ** element. + ** + ***************************************************************************/ + public String determineElementValue(Object o, + String element, + DMErrorManager dmErrorMgr) + { + // Value to return + String rtrnString = new String(""); + + // Get the Class name off of the Object + Class c = o.getClass(); + try + { + // Use reflection to obtain the appropriate field (attribute) + + // Get the Field (in Class c) that matches the element + Field tmpField = c.getField(element); + + // Get the Element object that is represented by the Field + Element e = (Element)tmpField.get(o); + + if ( e.isReadable() ) + { + // get the value off of the Element + rtrnString = e.getValue(); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - Element not readable"); + System.out.println("Value: " + element + " is not readable"); + } + + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("404"); + } + } + catch ( NoSuchFieldException nsfe ) + { + if (element.equals("_count") == true) + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - Element not an array"); + System.out.println("Element Cannont have count"); + } + dmErrorMgr.SetCurrentErrorCode("203"); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - Invalid Argument Error"); + System.out.println("Invalid data model element: " + element); + } + + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("201"); + } + } + catch ( SecurityException se ) + { + if ( DebugIndicator.ON ) + { + System.out.println(se); + System.out.println("Access to the information is denied"); + } + + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + catch ( IllegalAccessException iae ) + { + if ( DebugIndicator.ON ) + { + System.out.println(iae); + System.out.println("Underlying constructor is inaccessible"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + + return rtrnString; + + } // end of determineElementValue() + + /**************************************************************************** + ** + ** Method: doSet + ** Input: Object - the current Object (data model category) + ** String - Data Model Element that needs set + ** String - Value to use in the set + ** DMErrorManager - The Data Model Error manager + ** Output: none + ** + ** Description: This method performs all of the necessary steps in order + ** to process an LMSSetValue() request. The method uses + ** reflection to determine and find the element being set. + ** The method reports any errors while processing the + ** request. + ** + ***************************************************************************/ + public void doSet(Object o, + String element, + String value, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("CMICategory::doSet()"); + System.out.println("Object: " + o.getClass().getName()); + System.out.println("Element: " + element); + System.out.println("Value: " + value); + } + // Get the class from the object passed in + Class c = o.getClass(); + try + { + // Use reflection to obtain the appropriate field (attribute) + Field tmpField = c.getField(element); + + // Get the Element object that is represented by the Field + Element e = (Element)tmpField.get(o); + + // Check to see if the Element was implemented + if ( e.isImplemented() ) + { + // Check to see if the element was writeable + if ( e.isWriteable() || APIAdapterApplet.areweloading ) + { + // Verifiy the type of the value to be used for setting + // matches the type of the element to be set + if ( validateType(o,e,element,value,dmErrorMgr) ) + { + // set the value + e.setValue(value); + dmErrorMgr.SetCurrentErrorCode("0"); + if ( DebugIndicator.ON ) + { + System.out.println("Element: " + element + + " was set to [" + value + "]"); + } + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("*** INVALID LMSSetValue() CALL ***"); + System.out.println(" Invalid Type "); + System.out.println("Element: " + element + + " was NOT set!"); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not writeable + System.out.println("Error - Element not Writeable"); + System.out.println("Element: " + element + + " is not writeable"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("403"); + } + } + else + { + // Element was not implemented, check to see if it is a + // mandatory element + if ( e.isMandatory() ) + { + if ( DebugIndicator.ON ) + { + // Error - Mandatory Data Model Element not implemented + System.out.println( + "Error - Mandatory Element not Implemented"); + System.out.println("Mandatory Value: " + element + + " was not implemented"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("401"); + } + else + { + if ( DebugIndicator.ON ) + { + // Not an Error - Optional element not implemented + System.out.println( + "Warning - Optional Value Not Implemented"); + System.out.println("Optional Element: " + element + + " was not implemented"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("0"); + } + } + } + catch ( NoSuchFieldException nsfe ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - Invalid Argument Error"); + System.out.println("Invalid data model element: " + element); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("201"); + } + catch ( SecurityException se ) + { + if ( DebugIndicator.ON ) + { + System.out.println(se); + System.out.println("Access to the information is denied"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + catch ( IllegalAccessException iae ) + { + if ( DebugIndicator.ON ) + { + System.out.println(iae); + System.out.println("Underlying constructor is inaccessible"); + } + + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + + if ( DebugIndicator.ON ) + { + System.out.println("Exiting CMICategory::doSet()"); + } + + } // end of doSet() + + + /**************************************************************************** + ** + ** Method: validateType() + ** + ** Input: Object o - object for which the LMSSetValue is taking place + ** Element e - element class being set + ** String element - element (string representation) being set + ** String value - value being used for set + ** DMErrorManager dmErrorMgr - Data Model Error Manager + ** + ** Output: boolean value stating whether or not this is a valid LMSSetValue + ** request + ** + ** Description: Returns a boolean value which indicates whether or not + ** the LMSSetValue() request is valid. The method + ** uses the Data Model Validator to check to see if the + ** value to be used for setting is the correct type for + ** the element to be set. + ** + ***************************************************************************/ + protected boolean validateType(Object o, + Element e, + String element, + String value, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println(" Validating data type of the set value"); + System.out.println(" Check method: " + e.getType()); + System.out.println(" Element: " + element); + System.out.println(" Value: " + value); + } + + boolean result = false; + + DataModelValidator dmValidator = new DataModelValidator(); + Class dmClass = dmValidator.getClass(); + + // Set up the array of Class objects + // Each element in the array corresponds to a + // parameter of the method you want to invoke + Class[] parameterTypes = + new Class[] {e.getClass(), String.class}; + + // Declare a variable to hold the method + Method theMethod; + + // Declare an arry of objects for the arguments to the method + Object[] arguments = new Object[] {e,value}; + try + { + // Find the method on Class c that is represented by the + // name of the method ("performSet") and the parameter + // types + theMethod = dmClass.getMethod(e.getType(), parameterTypes); + + // Invoke the method that was found matching the method name + // and parameter types + Boolean theResult = (Boolean) theMethod.invoke(dmValidator,arguments); + result = theResult.booleanValue(); + } + catch ( NoSuchMethodException nsme ) + { + if ( DebugIndicator.ON ) + { + System.out.println(nsme); + System.out.println("No Such method: " + e.getType() + "()"); + } + + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + + } + catch ( IllegalAccessException iae ) + { + if ( DebugIndicator.ON ) + { + System.out.println(iae); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + catch ( InvocationTargetException ite ) + { + if ( DebugIndicator.ON ) + { + System.out.println(ite); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("101"); + } + + if ( DebugIndicator.ON ) + { + System.out.println(" Result from validation: " + result); + } + return result; + } + + +} // end of CMICategory Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIComments.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIComments.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIComments.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,272 @@ +/******************************************************************************* +** +** Filename: CMIComments.java +** +** File Description: The CMIComments class manages comments from the AU or +** Student. The comments are a collection of comments +** concatenated together for a given Assignable Unit (AU). +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM Version 1.1 +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/22/2000 S. Thropp PT - 114: Change the way student comments +** get set. The change to the CMI documentation +** was to get rid of the array of student +** comments and change this to be a concatenated +** string of comments. Changes were made to +** reflect this change. +** +** 11/15/2000 S. Thropp PT - 290: With the addition of the new +** cmi.comments_from_lms, this file was cleaned up +** to remove all references to instructorComments. +** File was also cleaned up to make cmi.comments +** both read and write. Also changed the name of +** the attribute to comments instead of +** studentComments. +** +** 01/28/2002 B. Capone Modified the setting of the return Error +** Code from 205 to 405 in performSet() if the +** string to be set is greater than the allowed +** length of 4096. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIComments extends CMICategory + implements Serializable +{ + // Student comments + public Element comments; + + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String comments - Comments from the AU or student + ** Output: none + ** + ** Description: A constructor used to initialize the comments. This + ** constructor takes in a String of comments to use for + ** initialization. + ** + ***************************************************************************/ + public CMIComments(String commentsString) + { + super( true ); + + comments = new Element(commentsString,"checkString4096","NULL", + true,true,false); + + } // end of constructor + + /**************************************************************************** + ** + ** Method: Default Constructor + ** Input: none + ** Output: none + ** + ** Description: Sets up the comments attribute with a default value. + ** + ***************************************************************************/ + public CMIComments() + { + super( true ); + + comments = + new Element("","checkString4096","NULL",true,true,false); + + } // end of default constructor + + + /************************************************************************ + ** Accessors to the CMIComments Data. AUs should not invoke these + ** methods. AUs should call LMSGetValue() + ************************************************************************/ + public Element getComments() + { + return comments; + } + + /************************************************************************ + ** Modifiers to the CMIComments Data. AUs should not invoke these + ** methods. AUs should call LMSSetValue() + ************************************************************************/ + public void setComments(String inComments) + { + comments.setValue(inComments); + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the necessary steps to retrieve the + ** value for the Comments data model element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // String to hold the value of the final element + String result = new String(""); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + // Error - Data Model Element not implemented + // *** There are no more subcategories in the CMI Comments class + // *** Since there are more tokens to process, the data model + // *** element was not implemented + if ( DebugIndicator.ON ) + { + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + + theRequest.getElement() + + "is not a valid data model element.\n"); + } + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + } + else + { + // No more tokens to process + + // determine the value associated with the element requested + result = comments.getValue(); + } + + // Done getting requested element. Let CMIRequest object know that + // processing of the LMSGetValue() is complete + theRequest.done(); + + return result; + } // end of performGet() + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs the necessary steps to set the + ** Comments Data Model Element. + ** The comments are collected as a String not to exceen 4096 bytes + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + // Check to see if the Request has more tokens to process + if ( !theRequest.hasMoreTokensToProcess() ) + { + + // get the value to use for setting off of the request + String content = theRequest.getValue(); + + // Check to make sure that the string to be used to set the comments + // does not exceed 4096 bytes. + if ( content.length() <= 4096) + { + // get the current student comments + String currentComments = comments.getValue(); + + // Concatenate the comments together + currentComments += content; + + // set the student comments with the new concatenated + // comments + comments.setValue(currentComments); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("***** INVALID LMSSetValue() CALL *****"); + System.out.println(" Invalid Type "); + System.out.println(" Element was not set! "); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + + } + else + { + // Error - Data Model Element not implemented + if ( DebugIndicator.ON ) + { + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + + theRequest.getElement() + + "is not a valid data model element.\n"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + + } + + // Done setting requested element. Let CMIRequest object know that + // processing of the LMSSetValue() is complete + theRequest.done(); + + } // end of performSet() + +} // end of CMIComments + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICommentsFromLms.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICommentsFromLms.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICommentsFromLms.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,256 @@ +/******************************************************************************* +** +** Filename: CMICommentsFromLms.java +** +** File Description: The CMICommentsFromLms class manages the comments that +** would come from an LMS or Instructor. These comments would +** be available to the student or AU upon request. +** The comments from this class are read only. +** +** Author: S. Thropp +** +** Contract Number: +** Company Name: CTC +** +** Module/Package Name: +** Module/Package Description: +** +** Design Issues: +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM Version 1.1 +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 R.Ball PT 290 - Initial creation of class to +** manage comments from the LMS. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; +import org.adl.samplerte.client.APIAdapterApplet; + +public class CMICommentsFromLms extends CMICategory + implements Serializable +{ + // Instructor comments + public Element comments_from_lms; + + // Number of Student Comments + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String comments - comments to be used to initialize the attribute + ** Output: none + ** + ** Description: Sets up the comments_from_lms with the comments that were + ** passed in + ** + ***************************************************************************/ + public CMICommentsFromLms(String comments) + { + super( true ); + comments_from_lms = new Element (comments,"checkString4096","NULL", + false,true,false); + + + } // end of constructor + + /**************************************************************************** + ** + ** Method: Default Constructor + ** Input: none + ** Output: none + ** + ** Description: Sets up the comment attributes with default values. + ** + ***************************************************************************/ + public CMICommentsFromLms() + { + super( true ); + comments_from_lms = new Element("","checkString4096","NULL", + false,true,false); + + } // end of default constructor + + + /************************************************************************ + ** Accessors to the CMIComments Data. AUs should not invoke these + ** methods. AUs should call LMSGetValue() + ************************************************************************/ + public Element getCommentsFromLms() + { + return comments_from_lms; + } + + /************************************************************************ + ** Modifiers to the CMIComments Data. AUs should not invoke these + ** methods. AUs should call LMSSetValue() + ************************************************************************/ + public void setCommentsFromLms(String inCommentsFromLMS) + { + comments_from_lms.setValue(inCommentsFromLMS); + } + + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - the tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the necessary steps to retrieve the + ** value for the suspend_data data model element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // String to hold the value of the final element + String result = new String(""); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // No more elements should exist + System.out.println("Error - Data Model Element not implemented\n"); + System.out.println("Element being processed: " + theRequest.getRequest() + + "element of the CMI Suspend Data " + + "Data Model Category"); + } + + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + } + else + { + // No more tokes to process + + // determine the value associated with the element requested + result = comments_from_lms.getValue(); + } + + // Done getting requested element. Let the CMIRequest object + // know that processing of the LMSGetValue() is done + theRequest.done(); + + return result; + } // end of performGet + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: The LMSGetValue() request is not allowed to be invoked + ** by an AU. Notify the operator + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + if (APIAdapterApplet.areweloading) { + // VERSION TO BYPASS SETVALUE RESTRICIONS + if ( !theRequest.hasMoreTokensToProcess() ) + { + String content = theRequest.getValue(); + if ( content.length() <= 4096) + { + String currentLMSComments = comments_from_lms.getValue(); + currentLMSComments += content; + comments_from_lms.setValue(currentLMSComments); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("***** INVALID DURING LOADING LMSSetValue() CALL *****"); + System.out.println(" Invalid Type "); + System.out.println(" Element was not set! "); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + else + { + // Error - Data Model Element not implemented + if ( DebugIndicator.ON ) + { + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + + theRequest.getElement() + + "is not a valid data model element.\n"); + } + dmErrorMgr.recNotImplementedError(theRequest); + + } + // Done setting requested element. Let CMIRequest object know that + // processing of the LMSSetValue() is complete + theRequest.done(); + + } else { + + if ( DebugIndicator.ON ) + { + // Error -- AU not allowed to call LMSSetValue on launch_data + System.out.println("Invalid LMSSetValue() request: " + + theRequest.getRequest()); + + System.out.println("Assignable Unit is not permitted to call" + + " LMSSetValue() for cmi.comments_from_lms"); + } + // Error - no more elements represented in data model + dmErrorMgr.SetCurrentErrorCode("403"); + } + } + } // end of CMICommentsFromLms + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICore.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICore.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMICore.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,574 @@ +/******************************************************************************* +** +** Filename: CMICore.java +** +** File Description: The CMICore class manages information required +** to be furnished by all LMS Systems. It contains +** data that all Assignable Units may depend upon at +** startup. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM Version 1.1 +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/05/2000 ADLI Project PT110 : Changed the check for CMIString256 +** to CMIString255 to reflect the CMI +** 3.4 document. +** +** 11/15/2000 S. Thropp PT 263 - Cosmetic changes to change the +** version number of SCORM. +*******************************************************************************/ + +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; +import org.adl.samplerte.client.APIAdapterApplet; + +public class CMICore extends CMICategory + implements Serializable +{ + // Indicates whether the student is being credited by the LMS for their + // performance in the AU + public Element credit; + + // Indication of whether the student has been in the AU before + public Element entry; + + // Indication of how or why the student left an AU + public Element exit; + + // Lesson exit point passed to the LMS the last time the student experienced + // the AU + public Element lesson_location; + + // Identification of student-related information that may be used to change + // the behavior of the AU + public Element lesson_mode; + + // Student status as determined by the LMS + public Element lesson_status; + + // Indication of the performance of the student during their last attempt on + // the AU + public CMIScore score; + + // Time spent in the AU during the session that is ending + public Element session_time; + + // Unique alpha-numeric identifier that refers to a single user of the LMS + public Element student_id; + + // Offical name of the student + public Element student_name; + + // Accumulated time of all the student sessions in the AU + public Element total_time; + + // The minimum number of tokens in a valid core Data Model Element + // request + static int CMICORE_MIN_NUM_TOKENS = 3; + + + /**************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: The default constructor sets up the class and initalizes + ** all of its attributes. + ** + ** See Element Constructor for more detail + ***************************************************************************/ + public CMICore() + { + // Set up default values for all attributes + + super( true ); + student_id = new Element("","checkIdentifier","NULL",false,true,true); + student_name = new Element("","checkString255","NULL",false,true,true); + lesson_location = new Element("","checkString255","NULL",true,true,true); + credit = new Element("","checkVocabulary","Credit",false,true,true); + lesson_status = new Element("","checkVocabulary","Status",true,true,true); + entry = new Element("","checkVocabulary","Entry",false,true,true); + total_time = new Element("","checkTimespan","NULL",false,true,true); + lesson_mode = new Element("","checkVocabulary","Mode",false,true,true); + exit = new Element("","checkVocabulary","Exit",true,false,true); + session_time = new Element("","checkTimespan","NULL",true,false,true); + score = new CMIScore(); + } + + /************************************************************************ + ** Accessers to the CMICore Data. AUs should not call these methods. + ** AUs should call LMSGetValue(). + ************************************************************************/ + public Element getCredit() + { + return credit; + } + public Element getEntry() + { + return entry; + } + public Element getExit() + { + return exit; + } + public Element getLessonLocation() + { + return lesson_location; + } + public Element getLessonMode() + { + return lesson_mode; + } + public Element getLessonStatus() + { + return lesson_status; + } + public CMIScore getScore() + { + return score; + } + public Element getSessionTime() + { + return session_time; + } + public Element getStudentId() + { + return student_id; + } + public Element getStudentName() + { + return student_name; + } + public Element getTotalTime() + { + return total_time; + } + + /************************************************************************ + ** Modifiers to the CMICore Data. AUs should not call these methods. + ** AUs should call LMSSetValue() + ************************************************************************/ + public void setCredit(String inCredit) + { + credit.setValue(inCredit); + } + public void setEntry(String inEntry) + { + entry.setValue(inEntry); + } + public void setExit(String inExit) + { + exit.setValue(inExit); + } + public void setLessonLocation(String inLessonLocation) + { + lesson_location.setValue(inLessonLocation); + } + public void setLessonMode(String inLessonMode) + { + lesson_mode.setValue(inLessonMode); + } + public void setLessonStatus(String inLessonStatus) + { + lesson_status.setValue(inLessonStatus); + } + public void setScore(CMIScore inScore) + { + score.getRaw().setValue( inScore.getRaw().getValue() ); + score.getMin().setValue( inScore.getMin().getValue() ); + score.getMax().setValue( inScore.getMax().getValue() ); + } + public void setSessionTime(String inSessionTime) + { + session_time.setValue(inSessionTime); + } + public void setStudentId(String inStudentID) + { + student_id.setValue(inStudentID); + } + public void setStudentName(String inStudentName) + { + student_name.setValue(inStudentName); + } + public void setTotalTime(String inTotalTime) + { + total_time.setValue(inTotalTime); + } + + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager, handles all + ** error reporting + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the LMSGetValue() request. The method + ** determines the value for the requested data element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Resultant value to return + String result = new String(""); + + // Check to make sure this is a valid LMSGetValue() request + if ( isValidCoreRequest(theRequest) ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + // Subcategory found in request + result = processSubcategory(theRequest,token,dmErrorMgr); + } + else + { + // No more tokes to process + + // Check to see if the request is for the children of Core Data + if ( theRequest.isAChildrenRequest() ) + { + // Set result to the string of children + result = getChildren(); + } + else + { + // determine the value associated with the element requested + result = determineElementValue(this,token,dmErrorMgr); + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Request being processed: " + theRequest.getRequest() + + "\nis not a valid request for the CMI Core\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done getting requested element. Let the CMIRequest object + // know that the LMSGetValue() processing is done + theRequest.done(); + + return result; + } // end of performGet + + /*************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String representation of the elements of the CMI Core + ** category + ** + ** Description: + ** This method returns a String containing the list of data elements + ** that CMI Core data object contains. + ** + ***************************************************************************/ + public String getChildren() + { + String children = "student_id,student_name,lesson_location," + + "credit,lesson_status,entry,score,total_time,lesson_mode," + + "exit,session_time"; + + return children; + } // end of getChildren + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - request to process + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs the LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + + if ( DebugIndicator.ON ) + { + System.out.println("Within cmicore PERFORMSET with request: " + theRequest); + } + + + // Check to see if this is a valid LMSSetValue() request + if ( isValidCoreRequest(theRequest) == true ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + // More tokens to process - subcategory found + String result = processSubcategory(theRequest,token,dmErrorMgr); + } + else + { + // No more tokens to process + + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + // Set the value + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recKeyWordError(token); + } + else + { + // Check to see if the set is for lesson_status + // SCOs are not permitted to set cmi.core.lesson_status + // to not attempted + if (token.equals("lesson_status") ) + { + if ( value.equals("not attempted") && APIAdapterApplet.areweloading==false ) + { + System.out.println("I WILL NOT ALLOW RE-SETTING not attempted!!!"); + dmErrorMgr.SetCurrentErrorCode("405"); + } + else + { + // Perform the setting of the value + doSet(this,token,value,dmErrorMgr); + } + } + else + { + // Perform the setting of the value + doSet(this,token,value,dmErrorMgr); + } + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Request being processed: " + theRequest.getRequest() + + "\nis not a valid request for the CMI Core\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done setting requested element. Let the request object know + // that the LMSSetValue() processing is finished + theRequest.done(); + + } // end of performSet + + /**************************************************************************** + ** + ** Method: processSubcategory + ** Input: CMIRequest - the current request being processed + ** String - the subcategory being processed + ** DMErrorManager - the Data Model Error Manager + ** + ** Output: String - result to be returned. If the request is for + ** an LMSSetValue() request an empty string is + ** returned + ** + ** Description: This method processes the subcategories of the CMICore + ** Data Model Category. The only valid subcategory of the + ** CMI Core class is the CMIScore class. Any other \ + ** subcategories are invalid - non compliant. + ** + ** If the request is for an LMSSetValue(), then an empty + ** String is returned. + ** + ***************************************************************************/ + private String processSubcategory(CMIRequest theRequest, + String theElement, + DMErrorManager dmErrorMgr) + { + String result = new String(""); + + try + { + Field tmpField = this.getClass().getField(theElement); + + // Call Get or Set on CMIScore + if ( theRequest.isForASetRequest() ) + { + // Set the value + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recKeyWordError(theRequest.getElement()); + } + else + { + // Invoke the performSet() on the subcategory + score.performSet(theRequest,dmErrorMgr); + } + } + else + { + if ( theElement.equals("score") ) + { + result = score.performGet(theRequest,dmErrorMgr); + } + else + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + } + } + catch ( NoSuchFieldException nsfe ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // *** The only subcategory in the CMI Core Data Category + // *** is the score. Any thing else is an error + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + theElement + + "is not a valid sub category of the CMI Core\n" + + "Data Model Category"); + } + + dmErrorMgr.SetCurrentErrorCode("401"); + } + catch ( SecurityException se ) + { + if ( DebugIndicator.ON ) + { + System.out.println(se); + System.out.println("Access to the information is denied"); + } + dmErrorMgr.SetCurrentErrorCode("101"); + } + + return result; + } + + /**************************************************************************** + ** + ** Method: isValidCoreRequest + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** + ** Output: Boolean value indicating whether or not the Core Request is + ** valid. + ** + ** Description: Checks to make sure that the request meets the minimum + ** requirements needed for a CMICore Model Element. + ** + ***************************************************************************/ + private boolean isValidCoreRequest(CMIRequest theRequest) + { + boolean rtrnFlag = false; + + // Check to see if the Request has the appropriate length for + // a CMI Core request + if ( theRequest.getTotalNumTokens() >= CMICORE_MIN_NUM_TOKENS ) + { + rtrnFlag = true; + } + + return rtrnFlag; + + } // end of isValidCoreRequest() + + /**************************************************************************** + ** + ** Method: showData + ** Input: none + ** Output: none + ** + ** Description: Displays the current state of the CMI Core Data object + ** + ***************************************************************************/ + public void showData() + { + if ( DebugIndicator.ON ) + { + System.out.println("CMI Core Object:"); + + System.out.println("\tstudent_id: " + getStudentId().getValue()); + System.out.println("\tstudent_name: " + getStudentName().getValue()); + System.out.println("\tlesson_location: " + getLessonLocation().getValue()); + System.out.println("\tcredit: " + getCredit().getValue()); + System.out.println("\tslesson_status: " + getLessonStatus().getValue()); + System.out.println("\tentry: " + getEntry().getValue()); + System.out.println("\texit: " + getExit().getValue()); + System.out.println("\tscore.raw: " + getScore().getRaw().getValue()); + System.out.println("\tscore.min: " + getScore().getMin().getValue()); + System.out.println("\tscore.max: " + getScore().getMax().getValue()); + System.out.println("\tsession_time: " + getSessionTime().getValue()); + System.out.println("\ttotal_time: " + getTotalTime().getValue()); + System.out.println("\tlesson_mode: " + getLessonMode().getValue()); + } + } +} // end of CMICore Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionData.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionData.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionData.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,699 @@ +/******************************************************************************* +** +** Filename: CMIInteractionData.java +** +** File Description: The CMIInteractionData class manages the interaction +** data elements. The interaction data is a recognized +** and recordable input or group of inputs from the +** student to the computer. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/05/2000 ADLI Project PT110 : Any references to CMIString256 were +** changed to CMIString255 to reflect +** the changes in the CMI 3.4 +** document. +** +** 09/28/2000 ADLI Project PT116 : The "response" element was changed +** to "correct_responses" to reflect +** changes in the CMI 3.4 data model. +** All related function names were +** also changed due to the use of +** reflection. +** +** 11/15/2000 S. Thropp PT292 : Changed the error code that was +** associated with the objective_id being +** and invalid type on a LMSSetValue() request. +** +** PT115: Changed objective_ids to become an +** array of ids instead of one id. +** +** 12/12/2000 J. Poltrack PTXXX: The objective_ids element changed to +** objectives.n.id +** +** 01/17/2001 S.Thropp PT374: Added more debug statments. +** Removed all references to hardcoded arrays +** and changed code to use Vectors. +** +** 05/14/2002 B. Capone PT1832: Changed the ID element in the +** constructor from checkString255 to +** checkIdentifier. Also, made same type of +** change in performSetForObjID(). +** +** 05/15/2002 B. Capone PT1976: Modified SetCurrentErrorCode for +** ArrayIndexOutOfBoundsException from 405 to +** 201 in the function performSetForResponse(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIInteractionData extends CMICategory + implements Serializable +{ + // Unique alphanumeric label created by the content developer + public Element id; + + // Indication of any objectives associated with the interaction + public Vector objectives; + + // Indication of when the interaction is available to the student + public Element time; + + // Indication of which category of interaction is recorded + public Element type; + + // Expected student feedback in the interaction + public Vector correct_responses; + + // Factor that is used to identify the relative importance of one + // interaction compared to another + public Element weighting; + + // Description of the computer measurable action of a student in an + // interaction + public Element student_response; + + // Judgement of the student's response + public Element result; + + // The time from the presentation of the stimulus to the completion of the + // measurable response + public Element latency; + + // Indicates if the Interaction Data has been initialized + private boolean initialized; + + /**************************************************************************** + ** + ** Method: CMIInteractionData + ** Input: none + ** Output: none + ** + ** Description: Default Constructor + ** + ***************************************************************************/ + public CMIInteractionData() + { + super( true ); + id = new Element("","checkIdentifier","NULL",true,false,false); + time = new Element("","checkTime","NULL",true,false,false); + type = new Element("","checkVocabulary","Interaction",true,false,false); + weighting = new Element("","checkDecimal","NULL",true,false,false); + student_response = + new Element("","checkFeedback","NULL",true,false,false); + result = new Element("","checkVocabulary","Result",true,false,false); + latency = new Element("","checkTimespan","NULL",true,false,false); + + correct_responses = new Vector(); + objectives = new Vector(); + + initialized = false; + + } // end of default constuctor + + /**************************************************************************** + ** Here are the accessers for the CMIInteractionData class. + ** AUs should not invoke these methods. AUs should call LMSGetValue() + ***************************************************************************/ + public Element getID() + { + return id; + } + public Element getLatency() + { + return latency; + }; + public Element getResult() + { + return result; + }; + public Element getStudentResponse() + { + return student_response; + } + public Element getTime() + { + return time; + } + public Element getType() + { + return type; + } + public Element getWeighting () + { + return weighting; + } + public Vector getObjID() + { + return objectives; + } + public Vector getCorrectResponses() + { + return correct_responses; + } + + /**************************************************************************** + ** Here are the modifiers for the CMIInteractionData class. + ** AUs should not invoke these methods. AUs should call LMSSetValue(). + ***************************************************************************/ + public void setID(String inId) + { + id.setValue(inId); + initialized = true; + } + public void setLatency(String inLatency) + { + latency.setValue(inLatency); + initialized = true; + } + public void setResult(String inResult) + { + result.setValue(inResult); + initialized = true; + } + public void setStudentResponse(String inStudentResponse) + { + student_response.setValue(inStudentResponse); + initialized = true; + } + public void setTime(String inTime) + { + time.setValue(inTime); + initialized = true; + } + public void setType(String inType) + { + type.setValue(inType); + initialized = true; + } + public void setWeighting(String inWeighting) + { + weighting.setValue(inWeighting); + initialized = true; + } + + public void setObjID(String inObjId, + int index) + { + objectives.add(index,inObjId); + } // end of setObjIDs() + + public void setCorrectResponses(CMIResponse inResponse,int index) + { + correct_responses.add(index,inResponse); + } // end of setResponse() + + public boolean isInitialized() + { + return initialized; + } + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** Output: none + ** + ** Description: This method performs all the necessary steps for an + ** LMSSetValue() request + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tInteractionData::performSet()"); + } + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tProcessing next token: " + token); + } + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + // More tokens to process - subcategory found + if ( (token.equals("objectives")) == true ) + { + token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tProcessing next token " + token); + } + performSetForObjID(token,theRequest,dmErrorMgr); + } + else if ( (token.equals("correct_responses")) == true ) + { + token = theRequest.getNextToken(); + if ( DebugIndicator.ON ) + { + System.out.println("\t\tProcessing next token " + token); + } + performSetForResponse(token,theRequest,dmErrorMgr); + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("\t\tError - Data Model Element not implemented"); + System.out.println("\t\tElement being processed: " + token + + " is not a valid element of the CMI Interactions\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + } + else + { + // No more tokens to process + // Set the value + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recKeyWordError(theRequest.getElement()); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tPerforming set"); + } + doSet(this,token,theRequest.getValue(),dmErrorMgr); + initialized = true; + } + } + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tExiting CMIInteractionData::peformSet()"); + } + + } // end of performSet() + + /**************************************************************************** + ** + ** Method: performSetForObjID + ** Input: String token - Array index as a token (String) + ** CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error Manager + ** Output: none + ** + ** Description: This method takes the necessary steps to set the + ** Objective IDs for the Interaction Data + ** + ***************************************************************************/ + private void performSetForObjID(String token, + CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tCMIInteractionData::performSetForObjID()"); + } + + // Convert the token to an array index + int arrayIndex = getArrayIndex(token,theRequest,dmErrorMgr); + String value = theRequest.getValue(); + + try + { + if ( DebugIndicator.ON ) + { + System.out.println( + "\t\tChecking to see if an element already exists"); + System.out.println("\t\tat array position " + arrayIndex); + } + + Element tmpElement = (Element)objectives.elementAt(arrayIndex); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tElement already exists"); + System.out.println("\t\tVector size: " + objectives.size()); + } + + // before setting the type make sure the type is valid + boolean result = validateType(this, + tmpElement, + "id", + value, + dmErrorMgr); + if (result) + { + // If this does not throw an ArrayOutOfBoundsException + // an element existed at the array index. Set the element + tmpElement.setValue(value); + objectives.set(arrayIndex,tmpElement); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tVector size: " + objectives.size()); + } + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("***** INVALID LMSSetValue() CALL *****"); + System.out.println(" Invalid Type "); + System.out.println("Element was NOT set!"); + System.out.println(""); + System.out.println("\t\tVector size: " + objectives.size()); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + catch ( ArrayIndexOutOfBoundsException e) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tElement does not already exists"); + } + + if ( arrayIndex <= objectives.size() ) + { + // Create an element using the request value. + Element tmpElement = + new Element(theRequest.getValue(), + "checkIdentifier","NULL",true,false,false); + + // before setting the type make sure the type is valid + boolean result = validateType(this, + tmpElement, + "id", + theRequest.getValue(), + dmErrorMgr); + + // result was true - valid type - perform set. + if ( result == true ) + { + objectives.add(arrayIndex,tmpElement); + if ( DebugIndicator.ON ) + { + System.out.println("\t\tVector size: " + objectives.size()); + } + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("***** INVALID LMSSetValue() CALL *****"); + System.out.println(" Invalid Type "); + System.out.println("Element was NOT set!"); + System.out.println(""); + System.out.println("\t\tVector size: " + objectives.size()); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + else + { + dmErrorMgr.SetCurrentErrorCode("201"); + } + + } + if ( DebugIndicator.ON ) + { + System.out.println("\t\tExiting performSetForObjID()"); + } + + } // end of performSetForObjID() + + /**************************************************************************** + ** + ** Method: performSetForResponse + ** Input: String token - Array index as a token (String) + ** CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error Manager + ** Output: none + ** + ** Description: This method takes the necessary steps to set the + ** Response for the Interaction Data** Input: String + ** + ***************************************************************************/ + private void performSetForResponse(String token, + CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tCMIInteractionData::performSetForResponses()"); + } + + // Convert the token to an array index + int arrayIndex = getArrayIndex(token,theRequest,dmErrorMgr); + String value = theRequest.getValue(); + + try + { + if ( DebugIndicator.ON ) + { + System.out.println( + "\t\tChecking to see if an element already exists"); + System.out.println("\t\tat array position " + arrayIndex); + } + + CMIResponse tmpResponse = + (CMIResponse)correct_responses.elementAt(arrayIndex); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tElement already exists"); + System.out.println("\t\tSet the value in the element and replace"); + System.out.println("\t\tVector size: " + correct_responses.size()); + } + + // If this does not throw an ArrayOutOfBoundsException + // an element existed at the array index. Set the element + tmpResponse.performSet(theRequest,dmErrorMgr); + correct_responses.set(arrayIndex,tmpResponse); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tVector size: " + correct_responses.size()); + } + } + catch ( ArrayIndexOutOfBoundsException e) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tElement does not already exists"); + System.out.println("\t\tVector size: " + correct_responses.size()); + } + + if (arrayIndex <= correct_responses.size() ) + { + CMIResponse response = new CMIResponse(); + response.performSet(theRequest,dmErrorMgr); + correct_responses.add(arrayIndex,response); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tVector size: " + correct_responses.size()); + } + } + else + { + dmErrorMgr.SetCurrentErrorCode("201"); + } + } + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tExiting performSetForResponses()"); + } + + } // end of performSetForResponse() + + /*************************************************************************** + ** + ** Method: getArrayIndex + ** Input: String token - array index as a string + ** CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error Manager + ** + ** Output: int - array index from the request + ** + ** Description: This method determines the array index based on the + ** request. + ** + ***************************************************************************/ + private int getArrayIndex(String token, + CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + int index=-1; + + // Token has to be an array index + try + { + // Convert the string integer to a number + Integer tmpInt= new Integer(token); + index = tmpInt.intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() + System.out.println( + "\t\tError - Data Model Element not implemented"); + System.out.println("\t\tInvalid data model element: " + + theRequest.getRequest()); + System.out.println("\t\tInvalid element " + + token + ", Array index expected"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("401"); + } + + return index; + } // end of getArrayIndex() + + /*************************************************************************** + ** + ** Method: getCount + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** + ** Output: String - the count of records matching the request + ** + ** Description: + ** + ***************************************************************************/ + public String getCount(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tCMIInteractionData::getCount()"); + } + + String result = new String(""); + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tProcessing next token: " + token); + } + + if ( token.equals("objectives") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tProcessing objectives._count"); + } + int count = 0; + count = objectives.size(); + + if (DebugIndicator.ON ) + { + System.out.println("\t\tNumber of objective ids: " + count); + } + Integer tmpInt = new Integer(count); + result = tmpInt.toString(); + } + else if ( token.equals("correct_responses") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("\t\tInteractionData:correct_responses._count"); + } + int count = 0; + count = correct_responses.size(); + + if (DebugIndicator.ON ) + { + System.out.println("\t\tNumber of correct_responses: " + count); + } + + Integer tmpInt = new Integer(count); + result = tmpInt.toString(); + } + else + { + if ( DebugIndicator.ON ) + { + // Error -- AU not allowed to call LMSGetValue on launch_data + System.out.println("\t\tInvalid LMSGetValue() request: " + + theRequest.getRequest()); + + System.out.println("\t\tSCO is not permitted to call" + + " LMSGetValue() for cmi.interactions"); + } + + // Error - no more elements represented in data model + dmErrorMgr.SetCurrentErrorCode("404"); + } + + if ( DebugIndicator.ON ) + { + System.out.println("\t\tReturning from getCount() count returning: " + + result); + } + + return result; + } + +} // end of CMIInteractionData Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionDataUtil.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionDataUtil.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionDataUtil.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,140 @@ +/******************************************************************************* +** +** Filename: CMIInteractionDataUtil.java +** +** File Description: +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 05/14/2002 B. Capone PT1832: Changed the ID element in the +** constructor from checkString255 to +** checkIdentifier. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIInteractionDataUtil extends CMICategory + implements Serializable +{ + public Element id; + public Element objectives; + public Element time; + public Element type; + public Element correct_responses; + public Element weighting; + public Element student_response; + public Element result; + public Element latency; + + /**************************************************************************** + ** + ** Method: CMIInteractionDataUtil + ** Input: none + ** Output: none + ** + ** Description: Default Constructor + ** + ***************************************************************************/ + public CMIInteractionDataUtil() + { + super( true ); + id = new Element("","checkIdentifier","NULL",true,false,false); + time = new Element("","checkTime","NULL",true,false,false); + type = new Element("","checkVocabulary","Interaction",true,false,false); + weighting = new Element("","checkDecimal","NULL",true,false,false); + student_response = + new Element("","checkFeedback","NULL",true,false,false); + result = new Element("","checkVocabulary","Result",true,false,false); + latency = new Element("","checkTimespan","NULL",true,false,false); + correct_responses = + new Element("","checkFeedback","NULL",true,false,false); + objectives = new Element("","checkString255","NULL",true,false,false); + + } // end of default constuctor + + /**************************************************************************** + ** Here are the accessers for the CMIInteractionDataUtil class. + ***************************************************************************/ + public Element getID() + { + return id; + } + public Element getLatency() + { + return latency; + }; + public Element getResult() + { + return result; + }; + public Element getStudentResponse() + { + return student_response; + } + public Element getTime() + { + return time; + } + public Element getType() + { + return type; + } + public Element getWeighting () + { + return weighting; + } + public Element getObjID() + { + return objectives; + } + public Element getCorrectResponses() + { + return correct_responses; + } + +} // end of CMIInteractionDataUtil \ No newline at end of file Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractions.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractions.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractions.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,422 @@ +/******************************************************************************* +** +** Filename: CMIInteractions.java +** +** File Description: The CMIInteractions class manages all of the Interaction +** CMI Data Model elements +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/28/2000 ADLI Project PT116 : The method "getChildren()" was +** changed to return "correct_responses" +** instead of "response". +** +** 11/15/2000 S. Thropp PT 292: Change the error code in +** performGet() to be a 404 element is write +** only. +** +** 01/17/2001 S. Thropp PT374: Added more debug statments. +** Removed all references to hardcoded arrays +** and changed code to use Vectors. +** +** 05/15/2002 B. Capone PT1976: Modified SetCurrentErrorCode for +** ArrayIndexOutOfBoundsException from 405 to +** 201 in the function performSet(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIInteractions extends CMICategory + implements Serializable +{ + // A recognized and recordable input or group of inputs from the + // student to the computer + public Vector interactions; + + /**************************************************************************** + ** + ** Method: CMIInteractions + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ** + ***************************************************************************/ + public CMIInteractions() + { + super( false ); + interactions = new Vector(); + + } // end of default constructor + + + /************************************************************************ + ** Accessers to the CMIInteraction Data. SCOs should not invoke these + ** methods. SCOs should call LMSGetValue() + ************************************************************************/ + public Vector getInteractions() + { + return interactions; + } + + /************************************************************************ + ** Modifiers to the CMIInteraction Data. SCOs should not invoke these + ** methods. SCOs should call LMSSetValue(). + ************************************************************************/ + public void setInteractions(CMIInteractionData inInteractions, + int index) + { + interactions.add(index,inInteractions); + + } // end of setInteractions() + + + /**************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String representation of the elements of the CMI Interactions + ** category + ** + ** Description: + ** This method returns a String containing the list of data elements that + ** CMI Score data object contains. + ** + ***************************************************************************/ + public String getChildren() + { + String children = + "id,objectives,time,type,correct_responses,weighting," + + "student_response,result,latency"; + + return children; + } // end of getChildren() + + /************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request. + ** DMErrorManager dmErroMgr - Error manager + ** Output: none + ** + ** Description: This method performs all the necessary steps for an + ** LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("\tIn CMIInteractions::performSet()"); + } + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("\tToken being processed: " + token); + } + + if ( theRequest.isAKeywordRequest() ) + { + // record a keyword error + dmErrorMgr.recKeyWordError(token); + } + else + { + // The next token must be an array. If not throw + // an exception for this request. + int index = -1; + + // Check to see if next token is an array index. For + // a LMSSetValue() this is true + try + { + // Try to convert the token to the index + Integer tmpInt = new Integer(token); + index = tmpInt.intValue(); + + // Get the Interaction Data at position of the index + CMIInteractionData tmpInteraction = + (CMIInteractionData)interactions.elementAt(index); + + // An interaction existed at the given index. + // Invoke the performSet() on the Interaction Data + tmpInteraction.performSet(theRequest,dmErrorMgr); + + // replace the old Interaction Data with the newly set + // Interaction + interactions.set(index,tmpInteraction); + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSSetValue() + System.out.println( + "\tError - Data Model Element not implemented"); + System.out.println("\tInvalid data model element: " + + theRequest.getRequest() + + " passed to LMSSetValue()"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + catch ( ArrayIndexOutOfBoundsException e) + { + if ( DebugIndicator.ON ) + { + System.out.println( + "\tFirst time setting the interaction data at the given index"); + } + + if ( index <= interactions.size() ) + { + // Create a new Interaction Data object + CMIInteractionData intData = new CMIInteractionData(); + + // Invoke the performSet() on the Interaction Data + intData.performSet(theRequest,dmErrorMgr); + + // Place the Interaction Data into the vector at the index position + interactions.add(index,intData); + } + else + { + dmErrorMgr.SetCurrentErrorCode("201"); + } + } + } + + // Done processing. Let the CMIRequest object know that processing + // of the LMSSetValue() is complete + theRequest.done(); + + if ( DebugIndicator.ON ) + { + System.out.println("\tCMIInteractions - performSet() exit"); + } + + return; + } // end of performSet + + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - empty + ** + ** Description: The LMSGetValue() request is not allowed to be invoked + ** by an SCO. Notify the operator + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + String result = new String(""); + int tokenCount = theRequest.getTotalNumTokens(); + + if ( DebugIndicator.ON ) + { + System.out.println("\tCMIInteractions::performGet()"); + } + + // Determine the type of request and process accordingly + if ( ( tokenCount == 3 ) && + ( theRequest.isAChildrenRequest() ) ) + { + if ( DebugIndicator.ON ) + { + System.out.println("\tProcessing a _children request"); + } + + result = getChildren(); + } + else if ( theRequest.isACountRequest() ) + { + if ( DebugIndicator.ON ) + { + System.out.println("\tProcessing a _count request"); + } + + // Determine the type of _count request + if (tokenCount == 3) + { + // _count request for CMIInteractions + int count = howManyInteractions(); + Integer tmpInt = new Integer(count); + result = tmpInt.toString(); + } + else + { + // _count request for CMIInteractionData + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("\tProcessing next token: " + token); + } + + try + { + Integer tmpInt = new Integer(token); + int index = tmpInt.intValue(); + + // Get the Objective Data that is positioned at the input index + CMIInteractionData intData = + (CMIInteractionData)interactions.elementAt(index); + + if ( intData.isInitialized() ) + { + result = intData.getCount(theRequest,dmErrorMgr); + } + else + { + String nextToken = theRequest.getNextToken(); + + if ( nextToken.equals("objectives") || + nextToken.equals("correct_responses") ) + { + result = "0"; + } + else + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed + System.out.println("\tError - Invalid LMSGetValue() request"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + catch ( ArrayIndexOutOfBoundsException e) + { + String nextToken = theRequest.getNextToken(); + + if ( ( tokenCount == 5) && + ( ( nextToken.equals("objectives") || + nextToken.equals("correct_responses") ) ) ) + { + result = "0"; + } + else + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + result = ""; + } + } + + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error -- SCO not allowed to call LMSGetValue on launch_data + System.out.println("\tInvalid LMSGetValue() request: " + + theRequest.getRequest()); + + System.out.println("\tSCO is not permitted to call" + + " LMSGetValue() for cmi.interactions"); + } + + dmErrorMgr.SetCurrentErrorCode("404"); + } + + if ( DebugIndicator.ON ) + { + System.out.println("\tReturning: " + result + " from CMIInteractions"); + System.out.println("\tCMIInteractions::performGet() exit"); + } + + // Done processing. Let CMIRequest object know the processing + // of the LMSGetValue() is done. + theRequest.done(); + + return result; + } + + /**************************************************************************** + ** + ** Method: howManyInteractions + ** Input: none + ** Output: int - number of interactions implemented + ** + ** Description: Calculates the number of interactions that have been + ** implemented. + ** + ***************************************************************************/ + private int howManyInteractions() + { + int count = 0; + + // must be asking for number of interactions + count = interactions.size(); + + return count; + } + +} // end of CMIInteractions Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionsUtil.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionsUtil.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIInteractionsUtil.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,88 @@ +/******************************************************************************* +** +** Filename: CMIInteractionsUtil.java +** +** File Description: +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIInteractionsUtil extends CMICategory + implements Serializable +{ + public CMIInteractionDataUtil interactions; + + /**************************************************************************** + ** + ** Method: CMIInteractionsUtil + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ** + ***************************************************************************/ + public CMIInteractionsUtil() + { + super( false ); + interactions = new CMIInteractionDataUtil(); + + } // end of default constructor + + + /********************************************** + ** Accessers to the CMIInteractionUtil Data. + **********************************************/ + public CMIInteractionDataUtil getInteractions() + { + return interactions; + } + +} // end of CMIInteractionsUtil \ No newline at end of file Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMILaunchData.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMILaunchData.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMILaunchData.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,264 @@ +/******************************************************************************* +** +** Filename: CMILaunchData.java +** +** File Description: The CMILaunchData class manages unique information +** generated at the Assignable Unit's creation that is +** needed for every use. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM Version 1.0 +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 292: Changed the error code for the +** performSet to map to the new Error Codes. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; +import org.adl.samplerte.client.APIAdapterApplet; + +public class CMILaunchData extends CMICategory + implements Serializable +{ + // Unique information generated at the Assignable Unit's creation that + // is needed for every use + public Element launch_data; + + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String launchData - Unique information generated at the AU's + ** creation that is needed for every use. + ** Output: none + ** + ** Description: Constructor for the launch data. + ** + ** See Element Constructor for more detail + ** + ***************************************************************************/ + public CMILaunchData(String launchData) + { + super( false ); + launch_data = new Element (launchData,"checkString4096","NULL", + false,true,true); + + } // end of constructor + + /**************************************************************************** + ** + ** Method: Default Constructor + ** Input: none + ** Output: none + ** + ** Description: Default constructor for the CMI Launch Data + ** + ** See Element Constructor for more detail + ***************************************************************************/ + public CMILaunchData() + { + super( false ); + launch_data = new Element("","checkString4096","NULL", + false,true,true); + + } // end of default constructor + + /************************************************************************ + ** Accessors to the CMILaunchData Data. AUs should not invoke these + ** methods. AUs should call LMSGetValue() + ************************************************************************/ + public Element getLaunchData() + { + return launch_data; + } + + /************************************************************************ + ** Modifiers to the CMILaunchData Data. AUs should not invoke these + ** methods. AUs should call LMSSetValue(). + ************************************************************************/ + public void setLaunchData(String inLaunchData) + { + launch_data.setValue(inLaunchData); + } + + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the necessary steps to retrieve the + ** value for the launch_data data model element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // String to hold the value of the final element + String result = new String(""); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // *** The only subcategory in the CMI Core Data Category + // *** is the score. Any thing else is an error + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + + theRequest.getRequest() + + "is not a valid element of the CMI Launch Data\n" + + "Data Model Category"); + } + + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + + } + else + { + // No more tokens to process + + // determine the value associated with the element requested + result = launch_data.getValue(); + } + + // Done getting requested element. Let the CMIRequest object know + // that processing of the LMSGetValue() request is done + theRequest.done(); + + return result; + } // end of performGet() + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: The LMSSetValue() request is not allowed to be invoked + ** by an AU. Notify the operator + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + if (APIAdapterApplet.areweloading) { + // VERSION TO BYPASS SETVALUE RESTRICIONS + if ( !theRequest.hasMoreTokensToProcess() ) + { + String content = theRequest.getValue(); + if ( content.length() <= 4096) + { + String currentlaunchdata = launch_data.getValue(); + launch_data.setValue(content); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("***** INVALID DURING LOADING LMSSetValue() CALL *****"); + System.out.println(" Invalid Type "); + System.out.println(" Element was not set! "); + } + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + else + { + // Error - Data Model Element not implemented + if ( DebugIndicator.ON ) + { + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + + theRequest.getElement() + + "is not a valid data model element.\n"); + } + dmErrorMgr.recNotImplementedError(theRequest); + + } + // Done setting requested element. Let CMIRequest object know that + // processing of the LMSSetValue() is complete + theRequest.done(); + + } else { + + if ( DebugIndicator.ON ) + { + // Error -- AU not allowed to call LMSSetValue on launch_data + System.out.println("Invalid LMSSetValue() request: " + + theRequest.getRequest()); + + System.out.println("Assignable Unit is not permitted to call" + + " LMSSetValue() for cmi.launch_data"); + } + // Error - no more elements represented in data model + dmErrorMgr.SetCurrentErrorCode("403"); + } + + } // end of performSet() + +} // end of CMILaunchData \ No newline at end of file Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectiveData.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectiveData.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectiveData.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,546 @@ +/******************************************************************************* +** +** Filename: CMIObjectiveData.java +** +** File Description: The CMIObjectiveData class manages the actual objective +** data. The objective data identifies how the student +** has performed on individual objectives in the +** SCO. +** +** Author: ADL Technical Team +** +** Contract Number: +** Company Name: CTC +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/22/2000 S. Thropp PT - 111: Changed all occurrences of status +** to statues to reflect changes in the CMI +** Guidelines for Interoperability revision +** 3.0.3 +** +** 10-31-2000 R. Ball PT 293: SCORM 1.1 Changes Objectives. +** modified score and status from being lists +** of scores and statuses to single items. +** +** 12-14-2000 S. Thropp PT 293: Fixed problem with an LMSGetValue() +** call The processSubcategory() was always +** calling performGet() on CMIScore regardless +** of the element. Added check to verify that +** the request was for cmi.objectives.0.score +** before calling performGet(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.lang.*; +import java.util.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIObjectiveData extends CMICategory + implements Serializable + +{ + // A developer defined, SCO specific identifier for an objective + public Element id; + + // The score obtained by the student after each attempt to master + // the objective + public CMIScore score; + + // The status obtained by the student after each attempt to master + // the objective + public Element status; + + // Indicates if the objective data has been initialized + private boolean initialized; + + static int CMIOBJECTIVEDATA_MIN_NUM_TOKENS = 3; + + /**************************************************************************** + ** + ** Method: CMIObjectiveData() + ** Input: none + ** + ** Output: none + ** + ** Description: This is the default constructor for the ObjectiveData + ** class. Default values are created for each element + ** + ***************************************************************************/ + public CMIObjectiveData() + { + super( true ); + + id = new Element("","checkIdentifier","NULL",true,true,false); + score = new CMIScore(); + status = new Element("","checkVocabulary","Status",true,true,false); + + } + + + /************************************************************************ + ** Accessers to the CMIObjectiveData. SCOs should not call these methods. + ** SCOs should call LMSGetValue(). + ************************************************************************/ + + public Element getStatus() + { + return status; + } + public CMIScore getScore() + { + return score; + } + public Element getId() + { + return id; + } + + /************************************************************************ + ** Modifiers to the CMIObjectives Data. SCOs should not call these methods. + ** SCOs should call LMSSetValue() + ************************************************************************/ + public void setStatus(String inStatus) + { + status.setValue(inStatus); + } + public void setScore(CMIScore inScore) + { + score.getRaw().setValue( inScore.getRaw().getValue() ); + score.getMin().setValue( inScore.getMin().getValue() ); + score.getMax().setValue( inScore.getMax().getValue() ); + } + public void setId(String inID) + { + id.setValue(inID); + } + + + public boolean isInitialized() + { + return initialized; + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager, handles all + ** error reporting + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the LMSGetValue() request. The method + ** determines the value for the requested data element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("CMIObjectiveData::performGet()"); + } + + // Resultant value to return + String result = new String(""); + + // Check to make sure this is a valid LMSGetValue() request + if ( isValidObjectiveDataRequest(theRequest) ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("Token: " + token); + } + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + // Subcategory found in request + result = processSubcategory(theRequest,token,dmErrorMgr); + } + else + { + // No more tokes to process + + // Check to see if the request is for the children of Objective Data + if ( theRequest.isAChildrenRequest() ) + { + // Set result to the string of children + result = getChildren(); + } + else + { + // determine the value associated with the element requested + result = determineElementValue(this,token,dmErrorMgr); + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Request being processed: " + + theRequest.getRequest() + + "\nis not a valid request for the CMI Objective\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done getting requested element. Let the CMIRequest object + // know that the LMSGetValue() processing is done + theRequest.done(); + + return result; + } // end of performGet + + /*************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String representation of the elements of the CMI Objective + ** category + ** + ** Description: + ** This method returns a String containing the list of data elements + ** that CMI Objective data object contains. + ** + ***************************************************************************/ + public String getChildren() + { + String children = "id,status,score"; + + return children; + } // end of getChildren + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - request to process + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs the LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Check to see if this is a valid LMSSetValue() request + if ( isValidObjectiveDataRequest(theRequest) == true ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + // More tokens to process - subcategory found + String result = processSubcategory(theRequest,token,dmErrorMgr); + } + else + { + // No more tokens to process + + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + // Set the value + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recKeyWordError(token); + } + else + { + // Perform the setting of the value + doSet(this,token,value,dmErrorMgr); + initialized = true; + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Request being processed: " + + theRequest.getRequest() + + "\nis not a valid request for the CMI Objective\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done setting requested element. Let the request object know + // that the LMSSetValue() processing is finished + theRequest.done(); + + } // end of performSet + + /**************************************************************************** + ** + ** Method: processSubcategory + ** Input: CMIRequest - the current request being processed + ** String - the subcategory being processed + ** DMErrorManager - the Data Model Error Manager + ** + ** Output: String - result to be returned. If the request is for + ** an LMSSetValue() request an empty string is + ** returned + ** + ** Description: This method processes the subcategories of the CMIObjectives + ** Data Model Category. The only valid subcategory of the + ** CMI Objectives class is the CMIScore class. Any other + ** subcategories are invalid - non compliant. + ** + ** If the request is for an LMSSetValue(), then an empty + ** String is returned. + ** + ***************************************************************************/ + private String processSubcategory(CMIRequest theRequest, + String theElement, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("In CMIObjectiveData::processSubcategory()"); + System.out.println("The Element: " + theElement); + } + String result = new String(""); + + try + { + Field tmpField = this.getClass().getField(theElement); + + // Call Get or Set on CMIScore + if ( theRequest.isForASetRequest() ) + { + // Set the value + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recKeyWordError(theRequest.getElement()); + } + else + { + // Invoke the performSet() on the subcategory + score.performSet(theRequest,dmErrorMgr); + } + } + else + { + if ( theElement.equals("score") ) + { + result = score.performGet(theRequest,dmErrorMgr); + } + // Determine if the Request is for a keyword. + else if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + } + } + catch ( NoSuchFieldException nsfe ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // *** The only subcategory in the CMI Objective Data Category + // *** is the score. Any thing else is an error + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + theElement + + "is not a valid sub category of the CMI " + + "Objectives\nData Model Category"); + } + + dmErrorMgr.SetCurrentErrorCode("401"); + } + catch ( SecurityException se ) + { + if ( DebugIndicator.ON ) + { + System.out.println(se); + System.out.println("Access to the information is denied"); + } + dmErrorMgr.SetCurrentErrorCode("101"); + } + + return result; + } + + /**************************************************************************** + ** + ** Method: isValidObjectiveDataRequest + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** + ** Output: Boolean value indicating whether or not the Request is + ** valid. + ** + ** Description: Checks to make sure that the request meets the minimum + ** requirements needed for a CMIObjectiveData Model Element. + ** + ***************************************************************************/ + private boolean isValidObjectiveDataRequest(CMIRequest theRequest) + { + boolean rtrnFlag = false; + + // Check to see if the Request has the appropriate length for + // a CMI Objective request + if ( theRequest.getTotalNumTokens() >= CMIOBJECTIVEDATA_MIN_NUM_TOKENS ) + { + rtrnFlag = true; + } + + return rtrnFlag; + + } // end of isValidObjectiveDataRequest() + + /**************************************************************************** + ** + ** Method: isValidRequest + ** Input: CMIRequest theRequest - tokenized request + ** DMErrorManager dmErrorMgr - instance of the Data Model Error + ** manager + ** + ** Output: boolean result indicating the validity of the request + ** + ** Description: This method checks to make sure the request is a valid + ** Data Model request. + ** + ***************************************************************************/ + public String isValidRequest(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + boolean flag = false; + String result = new String(""); + + if ( theRequest.getTotalNumTokens() <= 5) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("token: " + token); + } + + if (token.equals("id") || + token.equals("status") ) + { + if ( theRequest.hasMoreTokensToProcess() ) + { + flag = false; + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + dmErrorMgr.SetCurrentErrorCode("0"); + } + } + else if (token.equals("score") ) + { + flag = score.isValidRequest(theRequest); + if ( theRequest.isAChildrenRequest() ) + { + result = score.getChildren(); + } + } + } + else + { + // More than 5 tokens element is not implemented + dmErrorMgr.recNotImplementedError(theRequest); + } + + return result; + } + + + /**************************************************************************** + ** + ** Method: showData + ** Input: none + ** Output: none + ** + ** Description: Displays the current state of the CMI Objective Data object + ** + ***************************************************************************/ + public void showData() + { + if ( DebugIndicator.ON ) + { + System.out.println("CMI Objective Data Object:"); + + System.out.println("\tid: " + getId().getValue()); + System.out.println("\tstatus: " + getStatus().getValue()); + System.out.println("\tscore.raw: " + getScore().getRaw().getValue()); + System.out.println("\tscore.min: " + getScore().getMin().getValue()); + System.out.println("\tscore.max: " + getScore().getMax().getValue()); + } + } + + + + } // end of CMIObjectiveData Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectives.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectives.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectives.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,411 @@ +/******************************************************************************* +** +** Filename: CMIObjectives.java +** +** File Description: The CMIObjectives class manages the objective data for +** an Sharable Content Objects (SCOs). +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 R. Ball PT 293: SCORM 1.1 Changes, changed the +** getChildren() function to return the correct +** children. +** +** 05/15/2002 B. Capone PT1976: Modified SetCurrentErrorCode for +** ArrayIndexOutOfBoundsException from 405 to +** 201 in the function performSet(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.lang.*; +import java.util.*; +import java.lang.reflect.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIObjectives extends CMICategory + implements Serializable + +{ + // An array of CMIObjectiveData for the SCO + public Vector objectives; + + + // The minimum number of tokens in a valid objectives Data Model Element + // request + static int CMIOBJ_MIN_NUM_TOKENS = 3; + + /**************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ***************************************************************************/ + public CMIObjectives() + { + super( true ); + + // Create the vector to hold the objectives. + objectives = new Vector(); + + } // end of Default constructor + + /************************************************************************ + ** Accessors to the CMIObjective Data. SCOs should not invoke these + ** methods. SCOs should call LMSGetValue() + ************************************************************************/ + public Vector getObjectives() + { + return objectives; + } + + /************************************************************************ + ** Modifiers to the CMIObjective Data. SCOs should not invoke these + ** methods. SCOs should call LMSSetValue() + ************************************************************************/ + public void setObjectives(CMIObjectiveData objective, + int index) + { + objectives.add(index,objective); + } // end of setObjectives + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method takes the necessary steps to process + ** an LMSGetValue() request + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + if ( DebugIndicator.ON ) + { + System.out.println("CMIObjectives::performGet()"); + } + // Resultant value to return + String result = new String(""); + + // Check to make sure this is a valid LMSGetValue() request + if ( isValidObjRequest(theRequest) == true ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("Token being processed: " + token); + } + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + // Token has to be an array index + try + { + // Convert the string integer to a number + Integer tmpInt = new Integer(token); + int indexOfArr = tmpInt.intValue(); + + try + { + // Get the Objective Data that is positioned at the input index + CMIObjectiveData objData = + (CMIObjectiveData)objectives.elementAt(indexOfArr); + + // Invoke the performGet on the Objective Data returned. + result = objData.performGet(theRequest,dmErrorMgr); + } + catch (ArrayIndexOutOfBoundsException e) + { + if ( DebugIndicator.ON ) + { + System.out.println("Element does not exist at the given index"); + System.out.println("Index: " + indexOfArr ); + } + // if element has not been initialized, return Invalid + // Argument Error + dmErrorMgr.SetCurrentErrorCode("201"); + } + } + catch ( NumberFormatException nfe ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to LMSGetValue()"); + System.out.println("Array index required"); + } + // Notify error manager + dmErrorMgr.SetCurrentErrorCode("401"); + } + } + else + { + // No more tokens to process + + // Check to see if the request is for the children of Core Data + if ( theRequest.isAChildrenRequest() ) + { + // Set result to the string of children + result = getChildren(); + } + else if ( theRequest.isACountRequest() ) + { + int count = 0; + + count = objectives.size(); + + System.out.println("Count: " + count); + Integer tmpInt = new Integer(count); + result = tmpInt.toString(); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid request: " + + theRequest.getRequest()); + } + dmErrorMgr.recNotImplementedError(theRequest); + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid request: " + theRequest.getRequest()); + } + + dmErrorMgr.SetCurrentErrorCode("401"); + } + + // Done processing. Let CMIRequest object know the processing + // of the LMSGetValue() is done. + theRequest.done(); + + if ( DebugIndicator.ON ) + { + System.out.println("Returning from CMIObjectives::performGet()"); + System.out.println("Value returned: " + result); + } + return result; + } // end of performGet() + + + /**************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String representation of the data attributes of the objectives + ** Data Model + ** + ** Description: + ** This method returns a String containing the list of data elements + ** that CMI Objectives data object contains. + ** + ***************************************************************************/ + public String getChildren() + { + String children = "id,score,status"; + + return children; + } // end of getChildren() + + /*************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErroMgr - Error Manager + ** Output: none + ** + ** Description: This method takes the necessary steps to process + ** an LMSSetValue() request + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + + if ( DebugIndicator.ON ) + { + System.out.println("CMIObjectives::performSet()"); + } + + // The next token must be an array. If not throw + // an exception for this request. + int index = -1; + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + if ( DebugIndicator.ON ) + { + System.out.println("Token being processed: " + token); + } + + // Check to see if next token is an array index. For + // a LMSSetValue() this is true + try + { + // Try to convert the token to the index + Integer tmpInt = new Integer(token); + index = tmpInt.intValue(); + + // Get the Objective Data at position of the index + CMIObjectiveData tmpObj = + (CMIObjectiveData)objectives.elementAt(index); + + // An objective existed at the given index. + // Invoke the performSet() on the Objective Data + tmpObj.performSet(theRequest,dmErrorMgr); + + // replace the old ObjectiveData with the newly set Objective + // Data. + objectives.set(index,tmpObj); + + } + catch ( NumberFormatException nfe ) + { + if ( theRequest.isAKeywordRequest() == true) + { + dmErrorMgr.recKeyWordError(token); + } + else + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSSetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to LMSSetValue()"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + } + catch ( ArrayIndexOutOfBoundsException e) + { + if ( DebugIndicator.ON ) + { + System.out.println("First time setting the Objective Data"); + } + + if ( index <= objectives.size() ) + { + // A new Objective Data. + CMIObjectiveData objData = new CMIObjectiveData(); + + // Invoke performSet() on the new Objective Data + objData.performSet(theRequest,dmErrorMgr); + + // Place the Objective data into the vector at the + // index position + objectives.add(index,objData); + } + else + { + dmErrorMgr.SetCurrentErrorCode("201"); + } + } + + // Done processing. Let CMIRequest object know the processing + // of the LMSGetValue() is done. + theRequest.done(); + + return; + + } // end of performSet + + + /**************************************************************************** + ** + ** Method: isValidObjRequest + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** + ** Output: Boolean value indicating whether or not the Objectives Request + ** is valid. + ** + ** Description: Checks to make sure that the request meets the minimum + ** requirements needed for a CMIObjectives Model Element. + ** + ***************************************************************************/ + private boolean isValidObjRequest(CMIRequest theRequest) + { + boolean rtrnFlag = false; + + if ( theRequest.getTotalNumTokens() >= CMIOBJ_MIN_NUM_TOKENS ) + { + rtrnFlag = true; + } + + return rtrnFlag; + + } // end of isValidObjRequest() + +} // end of CMIObjectives Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectivesUtil.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectivesUtil.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIObjectivesUtil.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,88 @@ +/******************************************************************************* +** +** Filename: CMIObjectivesUtil.java +** +** File Description: +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIObjectivesUtil extends CMICategory implements Serializable +{ + public CMIObjectiveData objectives; + + /**************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ***************************************************************************/ + public CMIObjectivesUtil() + { + super( true ); + + objectives = new CMIObjectiveData(); + + + } // end of Default constructor + + /****************************************** + ** Accessors to the CMIObjectiveUtil Data. + *******************************************/ + public CMIObjectiveData getObjectives() + { + return objectives; + } + +} // end of CMIObjectivesUtil Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIRequest.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIRequest.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIRequest.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,1119 @@ +/******************************************************************************* +** +** Filename: CMIRequest.java +** +** File Description: This class represents a request, either LMSGetValue() or +** LMSSetValue(). The CMIRequest class is responsible for parsing +** the string parameter passed into these API calls. A CMIRequest is +** made up of the following parts: +** +** model: one and only one +** base category: one and only one +** subcategories: zero to many +** array indices: zero to many +** element: one and only one +** +** Examples: +** cmi.core.student_id +** model - cmi +** base category - core +** element - student_id +** +** cmi.student_data.tries.1.score.raw +** model - cmi +** base category - student_id +** subcategory[0] - tries +** subcategory[1] - score +** index[0] - 1 +** element - raw +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM Version 1.0 +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 08/07/2000 ADLI Team Fixed a formatting problem in showRequest() +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIRequest implements Serializable +{ + // The original LMSGetValue() or LMSSetValue() request un-tokenized + private String request; + + // The model token of the request + private String model; + + // The Base Category of the request + private String baseCategory; + + // A collection of Sub-Categories of the request (if any) + private int numSub = 10; + private String[] subcategory; + + // The number of Sub-Categories collected from the request (if any) + private int numOfSubCategories = 0; + + // A running total of the number of Sub-Categories returned (if any) + private int numOfSubCatReturned = 0; + + // A collection of array indices collected from the request (if any) + private int numInd = 10; + private Integer[] index; + + // The number of array indices collected from the request (if any) + private int numOfInd = 0; + + // A running total of the number of array indices returned (if any) + private int numOfIndReturned = 0; + + // The Element of the request + private String element; + + // The set value of the request (if LMSSetValue() request) + private String setValue; + + // The total number of tokens found in the request. If the request + // is an LMSSetValue() the set value is not counted as a token + private int totalNumberOfTokens = 0; + + // A running total of the number of tokens requested. Initialized to + // 1, because of the model. Design does not ask for the model. + private int tokensRequested = 1; + + // A running total of the number of tokes processed + private int tokensProcessed = 0; + + // Boolean value indicating if this Request is for an LMSGetValue() + private boolean getRequest; + + // Boolean value indicating if this Request is for an LMSSetValue() + private boolean setRequest; + + // This attribute keeps track of the types of tokens processed + // and keeps them in order for later use + // 1 - model + // 2 - base category + // 3 - sub category + // 4 - array index + // 5 - element + // 6 - value to use for set + // cmi.core.student_id -- 1,2,5 + // cmi.student_data.tries.n.score.raw -- 1,2,3,4,3,5 + // Used to indicate what the token is + private int numPat = 10; + private Integer[] pattern; + + static private int MODEL = 1; + static private int BASE_CATEGORY = 2; + static private int SUB_CATEGORY = 3; + static private int ARRAY_INDEX = 4; + static private int ELEMENT = 5; + static private int VALUE = 6; + + // initialize to 2 because the first two tokens would have + // been processed before this value is used. + static int pattern_counter = 2; + + // static method to increment the pattern_counter + static void incrementPatternCount() + { + pattern_counter++; + } + + // static method to reset the pattern_counter + static void resetPatternCounter() + { + pattern_counter = 2; + } + + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String theRequest - the request from the AU + ** boolean getRequestFlag - flag indicating whether or not this + ** request is for an LMSGetValue() + ** Output: none + ** + ** Description: This constructor is responsible for creating the request + ** object. The constructor takes the input request + ** (i.e. cmi.core.student_id) and parses the string into tokens. + ** + ***************************************************************************/ + public CMIRequest(String theRequest, + boolean getRequestFlag) + { + if ( DebugIndicator.ON ) + { + if ( getRequestFlag ) + { + System.out.println("Building CMIRequest for a LMSGetValue(" + + theRequest + ") "); + } + else + { + System.out.println("Building CMIRequest for a LMSSetValue(" + + theRequest + ") "); + } + } + + // Set up initial values + request = theRequest; + model = new String(""); + baseCategory = new String(""); + element = new String(""); + setValue = new String(""); + + getRequest = getRequestFlag; + + + //*********************** + // Set up index array + //********************** + index = new Integer[numInd]; + + // assign a value to each array element and print + for ( int i = 0; i < index.length; i++ ) + { + index[i] = new Integer(-1); + } + + //*********************** + // Set up pattern array + //********************** + pattern = new Integer[numPat]; + + // assign a value to each array element and print + for ( int j = 0; j < pattern.length; j++ ) + { + pattern[j] = new Integer(-1); + } + + //************************** + // Set up subcategory array + //************************** + subcategory = new String[numSub]; + + // assign a value to each array element and print + for ( int z = 0; z < subcategory.length; z++ ) + { + subcategory[z] = new String("-1"); + } + + // used to hold the set value on an LMSSetValue() + String theSetValue = new String(""); + + // used to hold request + String theNewRequest = new String(""); + + // Check to see if this is a LMSGetValue() request + if ( getRequest ) + { + setRequest = false; + parseGetRequest(theRequest); + } + else + { + setRequest = true; + // Break up the request into into tokens + StringTokenizer setTok = new StringTokenizer(theRequest, ",", false); + int numTokensForSet = setTok.countTokens(); + int numTokensProcessed = 0; + + theNewRequest = setTok.nextToken(); + numTokensProcessed++; + + if ( DebugIndicator.ON ) + { + System.out.println("Request: [" + theNewRequest + "]"); + } + + if ( numTokensForSet == 1 ) + { + theSetValue = new String(""); + } + else + { + + //Loop to build the value for a LMSSetValue() + while (numTokensProcessed < numTokensForSet) + { + theSetValue += setTok.nextToken(); + numTokensProcessed++; + + if (numTokensProcessed != numTokensForSet) + { + theSetValue += ","; + } + } + + if ( DebugIndicator.ON ) + { + System.out.println("Set Value: [" + theSetValue + "]"); + } + } + + totalNumberOfTokens++; + parseSetRequest(theNewRequest,theSetValue); + } + + if ( DebugIndicator.ON ) + { + this.showRequest(); + } + + } // end of CMIRequest() + + /*************************************************************************** + ** + ** Method: getModel() + ** Input: none + ** Output: String - data model used + ** + ** Description: Indicates the data model used + ** + ***************************************************************************/ + public String getModel() + { + return model; + } + + + /*************************************************************************** + ** + ** Method: isForASetRequest() + ** Input: none + ** Output: boolean setRequest + ** + ** Description: Indicates whether or not the current request is for + ** an LMSSetValue() request + ** + ***************************************************************************/ + public boolean isForASetRequest() + { + return setRequest; + } + + /*************************************************************************** + ** + ** Method: isAKeywordRequest() + ** Input: none + ** Output: boolean result + ** + ** Description: Indicates whether or not the current request is for + ** keyword request--> _children, _count or _version + ** + ***************************************************************************/ + public boolean isAKeywordRequest() + { + boolean result = false; + if ( (isAChildrenRequest()) || + (isACountRequest()) || + (isAVersionRequest()) ) + { + result = true; + } + return result; + } + + /*************************************************************************** + ** + ** Method: isAChildrenRequest() + ** Input: none + ** Output: boolean result + ** + ** Description: Indicates whether or not the current request is for + ** an _children request + ** + ***************************************************************************/ + public boolean isAChildrenRequest() + { + boolean result = false; + if ( element.equals("_children") ) + { + result = true; + } + return result; + } + + /*************************************************************************** + ** + ** Method: isACountRequest() + ** Input: none + ** Output: boolean result + ** + ** Description: Indicates whether or not the current request is for + ** an _count request + ** + ***************************************************************************/ + public boolean isACountRequest() + { + boolean result = false; + if ( element.equals("_count") ) + { + result = true; + } + return result; + } + + /*************************************************************************** + ** + ** Method: isAVersionRequest() + ** Input: none + ** Output: boolean result + ** + ** Description: Indicates whether or not the current request is for + ** an _version request + ** + ***************************************************************************/ + public boolean isAVersionRequest() + { + boolean result = false; + if ( element.equals("_version") ) + { + result = true; + } + return result; + } + /*************************************************************************** + ** + ** Method: getRequest + ** Input: none + ** Output: String request - Original unparsed request + ** + ** Description: This method returns the original unparsed request + ** + ***************************************************************************/ + public String getRequest() + { + return request; + } + + /*************************************************************************** + ** + ** Method: getBaseCategory + ** Input: none + ** Output: String baseCategory - the base category found in request + ** + ** Description: This method returns the Base Category + ** + ***************************************************************************/ + public String getBaseCategory() + { + tokensRequested++; + return baseCategory; + } + + /*************************************************************************** + ** + ** Method: getValue + ** Input: none + ** Output: String value - the set value + ** + ** Description: This method returns the Value to be used for setting. + ** + ***************************************************************************/ + public String getValue() + { + return setValue; + } + + /*************************************************************************** + ** + ** Method: getElement + ** Input: none + ** Output: String value - the element + ** + ** Description: This method returns the Element of the request + ** + ***************************************************************************/ + public String getElement() + { + return element; + } + + /*************************************************************************** + ** + ** Method: getTotalNumTokens + ** Input: none + ** Output: String totalNumberOfTokens - The total number of tokens + ** in the request + ** + ** Description: This method returns the Total Number of Tokens + ** + ***************************************************************************/ + public int getTotalNumTokens() + { + return totalNumberOfTokens; + } + + /*************************************************************************** + ** + ** Method: getNumSubCat() + ** Input: none + ** Output: int - the number of subcategories + ** + ** Description: This method returns the number of sub categories + ** in the request + ** + ***************************************************************************/ + public int getNumSubCat() + { + return numOfSubCategories; + } + + /*************************************************************************** + ** + ** Method: getNumIndices() + ** Input: none + ** Output: int - the number of indicies + ** + ** Description: This method returns the number of indices found + ** in the request + ** + ***************************************************************************/ + public int getNumIndices() + { + return numOfInd; + } + + /*************************************************************************** + ** + ** Method: getIndex() + ** Input: none + ** Output: Integer - the position in the array to find the index + ** + ** Description: This method returns the index found at the input position + ** + ***************************************************************************/ + public Integer getIndex( int position ) + { + return index[position]; + } + + /*************************************************************************** + ** + ** Method: getSubCategory() + ** Input: int - which subcategory + ** Output: String - the subcategory + ** + ** Description: This method returns the subcategory found at the + ** input position + ** + ***************************************************************************/ + public String getSubCategory(int position) + { + String subCat = new String ("-1"); + + if ( (position >=0) && (position < 10) ) + { + subCat = subcategory[position]; + } + + return subCat; + } + + /*************************************************************************** + ** + ** Method: parseGetRequest + ** Input: StringTokenizer stk - String Tokenizer holding request + ** Output: none + ** + ** Description: This method performs the necessary steps to parse + ** an LMSGetValue() request. + ** + ***************************************************************************/ + private void parseGetRequest(String theRequest) + { + // Break up the request into tokens + StringTokenizer stk = new StringTokenizer(theRequest, ".", false); + + // set the total number of tokens in the request + totalNumberOfTokens = totalNumberOfTokens + stk.countTokens(); + + // First token is the model + model = stk.nextToken(); + tokensProcessed++; + + pattern[0] = ( new Integer(MODEL) ); + + // Second token is the baseCategory + baseCategory = stk.nextToken(); + tokensProcessed++; + + pattern[1] = (new Integer(BASE_CATEGORY)); + + if ( stk.hasMoreTokens() ) + { + // The only thing that can follow a category is + // either another category (subcategory), array index, + // or an element. + + // declare a boolean to be used to indicate when processing is done + boolean done=false; + + // Loop until done + while ( !done ) + { + // Check to see if we are on the last token (ELEMENT) + if ( onLastToken() ) + { + // Last token to be processed, this is assigned + // to the element attribute + String temp = stk.nextToken(); + + try + { + // Try converting the token to an Integer. If this + // is successfull, then we are dealing with an array index + Integer tmpInt = new Integer(temp); + int tmpIndex = findNextIndexLoc(); + + // Store off the array index + index[tmpIndex] = tmpInt; + + // Increment the number of indicies + numOfInd++; + + int tmpIndex1 = findNextPatternLoc(); + + // Store off the array index pattern number + pattern[tmpIndex1] = ( new Integer(ARRAY_INDEX) ); + + // The last subcategory processed is the element. + // Use the numOfSubCategores as the base index. Need + // to subtract 1 to get to the correct index. Currently + // the only data model element that falls into this + // category is cmi.objectives.n.status.n + element = subcategory[numOfSubCategories - 1]; + + tmpIndex1 = findNextPatternLoc(); + pattern[tmpIndex1] = ( new Integer(ELEMENT) ); + + + } + catch ( NumberFormatException nfe ) + { + element = temp; + int tmpIndex = findNextPatternLoc(); + + pattern[tmpIndex] = ( new Integer(ELEMENT) ); + } + + // increment the tokens processed + tokensProcessed++; + + done = true; + } // end of if onLastToken() + else + { + // Check to see if next token is an array index + // determineNextToken() will set index up if the element + // being processed is an array index. + // + // cmi.objectives.n.id (index will be set to n on + // return from method + // + // cmi.core.score.raw (subcategory1 or subcategory2 + // will be set to score on return from method + determineNextToken(stk); + } + } // end of while + } + else + { + // Request only had two tokens: (i.e. "cmi.comments" or "cmi.suspend_data") + // Need to set the element attribute to the base category + element = baseCategory; + } + } // end parseGetRequest + + + /*************************************************************************** + ** + ** Method: parseSetRequest + ** Input: StringTokenizer stk - String Tokenizer holding request + ** Output: none + ** + ** Description: This method performs the necessary steps to parse + ** an LMSSetValue() request. + ** + ***************************************************************************/ + private void parseSetRequest(String theRequest, + String theSetValue) + { + if ( DebugIndicator.ON ) + { + System.out.println("In CMIRequest::parseSetRequest"); + } + + // Break up the request into tokens + StringTokenizer stk = new StringTokenizer(theRequest, ".", false); + + // set the total number of tokens in the request + totalNumberOfTokens = totalNumberOfTokens + stk.countTokens(); + + // First token is the model + model = stk.nextToken(); + tokensProcessed++; + + pattern[0] = (new Integer(MODEL)); + + // Second token is the baseCategory + baseCategory = stk.nextToken(); + tokensProcessed++; + + pattern[1] = (new Integer(BASE_CATEGORY)); + + if ( stk.hasMoreTokens() ) + { + // The only thing that can follow a category is + // either another category (subcategory), array index, + // or an element. + + // declare a boolean to be used to indicate when processing is done + boolean done=false; + + // Loop until done + while ( !done ) + { + // Check to see if we are on the last token (ELEMENT) + if ( onLastToken() ) + { + // Last token to be processed, this is assigned + // to the element attribute + setValue = theSetValue; + tokensProcessed++; + + int tmpIndex = findNextPatternLoc(); + + pattern[tmpIndex] = (new Integer(VALUE)); + done = true; + } // end of if onLastToken() + else if ( (totalNumberOfTokens - tokensProcessed) == 2 ) + { + element = stk.nextToken(); + tokensProcessed++; + int tmpIndex = findNextPatternLoc(); + + pattern[tmpIndex] = (new Integer(ELEMENT)); + } + else + { + // Check to see if next token is an array index + // determineNextToken() will set index up if the element + // being processed is an array index. + // + // cmi.objectives.n.id (index will be set to n on + // return from method + // + // cmi.core.score.raw (subcategory1 or subcategory2 + // will be set to score on return from method + determineNextToken(stk); + } + } // end of while + } + else + { + // Last token to be processed, this is assigned + // to the element attribute + setValue = theSetValue; + tokensProcessed++; + int tmpIndex = findNextPatternLoc(); + + pattern[tmpIndex] = (new Integer(VALUE)); + } + + } // end parseGetRequest + + /***************************************************************************** + ** + ** Method: determineNextToken + ** Input: StringTokenizer stk - String Tokenizer holding the request + ** Output: none + ** + ** Description: This method is used to determine the next token. The + ** method first attempts to see if the next token is an + ** array element. If so, the method stores off the array + ** element. If the next element is a subcategory, + ** the method stores off the subcategory + ** + ***************************************************************************/ + private void determineNextToken(StringTokenizer stk) + { + // Get the next token from the String Tokenizer + String temp = stk.nextToken(); + + // increment the number of tokens processed + tokensProcessed++; + + // Check to see if the token is an array index or a + // subcategory + try + { + // Try converting the token to an Integer. If this + // is successfull, then we are dealing with an array index + Integer tmpInt = new Integer(temp); + + int tmpIndex = findNextIndexLoc(); + + // Store off the array index + index[tmpIndex] = tmpInt; + + // Increment the number of indicies + numOfInd++; + + int tmpIndex1 = findNextPatternLoc(); + + // Store off the array index pattern number + pattern[tmpIndex1] = ( new Integer(ARRAY_INDEX) ); + } + catch ( NumberFormatException nfe ) + { + // Token could not be converted to a number + // Dealing with a subcategory + + int tmpIndex = findNextSubLoc(); + + // store off the subcategory + subcategory[tmpIndex] = temp; + + // Increment the number of subcategories + numOfSubCategories++; + + int tmpIndex1 = findNextPatternLoc(); + + // Store off the subcategory pattern number + pattern[tmpIndex1] = (new Integer(SUB_CATEGORY)); + } + } // end of determineNextToken() + + + /**************************************************************************** + ** + ** Method: onLastToken + ** Input: none + ** Output: boolean result indicating whether or not the code is on the + ** last token + ** + ** Description: This method determines if we are on the last token + ** + ***************************************************************************/ + private boolean onLastToken() + { + boolean rtrnFlag = false; + + if ( (totalNumberOfTokens - tokensProcessed) == 1 ) + { + rtrnFlag = true; + } + return rtrnFlag; + } // end of onLastToken() + + + /*************************************************************************** + ** + ** Method: getNextToken + ** Input: none + ** Output: String - next available token + ** + ** Description: This method uses the pattern collection to determine + ** the next (in order from original request) availabe + ** token. + ** + ***************************************************************************/ + public String getNextToken() + { + // Value to return + String rtrnValue = new String(""); + + try + { + Integer tmpPat = pattern[pattern_counter]; + // Check pattern counter to see what the next token will be + int tmpPattern = tmpPat.intValue(); + + // Determine the appropriate value to return based on the pattern + if ( tmpPattern == SUB_CATEGORY ) + { + try + { + // Dealing with sub categories + rtrnValue = subcategory[numOfSubCatReturned]; + numOfSubCatReturned++; + } + catch ( IndexOutOfBoundsException ioobe ) + { + System.out.println(ioobe); + } + } + else if ( tmpPattern == ARRAY_INDEX ) + { + try + { + Integer tmpIndex = index[numOfIndReturned]; + numOfIndReturned++; + // Dealing with array indexes + rtrnValue = tmpIndex.toString(); + + } + catch ( IndexOutOfBoundsException ioobe ) + { + System.out.println(ioobe); + } + } + else if ( tmpPattern == ELEMENT ) + { + // Dealing with elements + rtrnValue = element; + + // on last token (element) reset static pattern + // count + resetPatternCounter(); + } + else if ( tmpPattern == VALUE ) + { + // Dealing with set values + rtrnValue = setValue; + } + + // If the pattern that is being processed is not an element + // increment the static pattern count + if ( tmpPattern != ELEMENT ) + { + incrementPatternCount(); + } + tokensRequested++; + } + catch ( IndexOutOfBoundsException ioobe ) + { + System.out.println(ioobe); + } + + return rtrnValue; + } // end of getNextToken() + + /*************************************************************************** + ** + ** Method: hasMoreTokensToProcess() + ** Input: none + ** Output: boolean returnValue - indicates how many tokens are left + ** to process + ** + ** Description: Determines if there are more tokens left to process + ** + ***************************************************************************/ + public boolean hasMoreTokensToProcess() + { + boolean rtrnFlag = true; + + // If dealing with LMSSetValue() request don't count the setValue + if ( setRequest ) + { + if ( ((totalNumberOfTokens - 1) - tokensRequested) == 0 ) + { + rtrnFlag = false; + } + } + else + { + if ( (totalNumberOfTokens - tokensRequested) == 0 ) + { + rtrnFlag = false; + } + } + + return rtrnFlag; + } // end of hasMoreTokensToProcess() + + /*************************************************************************** + ** + ** Method: done + ** Input: none + ** Output: none + ** + ** Description: This method is invoked when the processing of a request + ** is finished. It resets counters used in processing + ** + ***************************************************************************/ + public void done() + { + resetPatternCounter(); + tokensRequested=1; + numOfSubCatReturned = 0; + numOfIndReturned = 0; + return; + } + + /*************************************************************************** + ** + ** Method: findNextPatternLoc + ** Input: none + ** Output: int - The next available position in the pattern array + ** + ** Description: Determines the next available position in the pattern + ** array and returns it to the caller + ** + ***************************************************************************/ + private int findNextPatternLoc() + { + int result = -1; + int value = -1; + + for ( int i = 0; i <= numPat; i++ ) + { + if ( value == pattern[i].intValue() ) + { + result = i; + break; + } + } + + return result; + } + + /*************************************************************************** + ** + ** Method: findNexIndexLoc + ** Input: none + ** Output: int - The next available position in the index array + ** + ** Description: Determines the next available position in the index + ** array and returns it to the caller + ** + ***************************************************************************/ + private int findNextIndexLoc() + { + int result = -1; + int value = -1; + + for ( int i = 0; i <= numInd; i++ ) + { + if ( value == index[i].intValue() ) + { + result = i; + break; + } + } + + return result; + } + + /*************************************************************************** + ** + ** Method: findNexSubLoc + ** Input: none + ** Output: int - The next available position in the subcategory array + ** + ** Description: Determines the next available position in the subcategory + ** array and returns it to the caller + ** + ***************************************************************************/ + private int findNextSubLoc() + { + int result = -1; + String tmpString = new String("-1"); + for ( int i = 0; i <= numSub; i++ ) + { + if ( subcategory[i].equalsIgnoreCase(tmpString) ) + { + result = i; + break; + } + } + + return result; + } + + /*************************************************************************** + ** + ** Method: showRequest() + ** Input: none + ** Output: none + ** + ** Description: Sends important information about the request to System.out + ** + ** + ***************************************************************************/ + public void showRequest() + { + if ( DebugIndicator.ON ) + { + System.out.println("Base Category: " + baseCategory); + System.out.println("Element: " + element); + System.out.println("Model: " + model); + System.out.println("Number of Indices: " + numOfInd); + System.out.println("Number of SubCategories: " + numOfSubCategories); + + for ( int i=0; i < numOfSubCategories; i++) + { + System.out.println("Subcategory[" + i + "]: " + subcategory[i]); + } + + for ( int j=0; j < numOfInd; j++) + { + System.out.println("Index[" + j + "]: " + index[j]); + } + + for ( int x=0; x < numPat; x++) + { + if ( pattern[x].intValue() > -1 ) + { + System.out.println("Pattern[" + x + "]: " + pattern[x]); + } + } + + if ( this.isForASetRequest() ) + { + System.out.println("Set Value: " + setValue); + } + } + + } + +} // end of CMIRequest Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIResponse.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIResponse.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIResponse.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,178 @@ +/******************************************************************************* +** +** Filename: CMIResponse.java +** +** File Description: The CMIResponse class manages expected student +** feedback in the interaction. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/28/2000 ADLI Project PT116 : The "value" and "description" +** elements were removed and the +** "pattern" element was added to +** reflect the changes in the CMI 3.4 +** Guidelines For Interoperability +** document. All methods were modified +** to reflect these changes +** +** 11/15/2000 S.Thropp PT 263: Added comment describing pattern +** attribute and removed reference to version +** of SCORM. +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIResponse extends CMICategory + implements Serializable +{ + // Definition of possible student response + public Element pattern; + + /*************************************************************************** + ** + ** Method: Constructor + ** Input: none + ** Output: none + ** + ** Description: Default constructor + ** + ***************************************************************************/ + public CMIResponse() + { + super( true ); + pattern = new Element("","checkFeedback","NULL",true,false,false); + } // end of default constructor + + /************************************************************************ + ** Accesser to the CMIResponse Data. AUs should not call this method. + ** AUs should call LMSGetValue(). + ************************************************************************/ + public Element getPattern() + { + return pattern; + } + + public boolean isInitialized() + { + boolean flag = false; + if ( pattern.isInitialized() ) + { + flag = true; + } + + return flag; + } + /************************************************************************ + ** Modifier to the CMIResponse Data. AUs should not call this method. + ** AUs should call LMSSetValue(). + ************************************************************************/ + public void setPattern(String inPattern) + { + pattern.setValue(inPattern); + } + + + /*************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error Manager + ** Output: none + ** + ** Description: This method performs all of the necessary steps to + ** process an LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + token + + "is not a valid element of the CMI Response\n" + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + // No more tokens to process + if (theRequest.isAKeywordRequest() == false) + { + + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + // Set the value + doSet(this,token,value,dmErrorMgr); + } + else + { + dmErrorMgr.recKeyWordError(token); + } + } + } // end of performSet() + + +} // end of CMIResponse + Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIScore.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIScore.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIScore.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,342 @@ +/******************************************************************************* +** +** Filename: CMIScore.java +** File Description: The CMIScore class manages information indicating +** the performance of the student during their last attempt +** on the SCO (AU). +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S.Thropp PT 263: Removed reference to SCORM version +** +** 12/27/2001 Jeff Falls changed check call from checkDecimal() to +** checkScoreDecimal() to test the +** "cmi.core.score" elements for negative +** values +** +** 03/20/2002 Bill Capone Added a "SetCurrentErrorCode" to "0" (zero) +** in performGet(). +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIScore extends CMICategory + implements Serializable +{ + // Numerical representation of student performance in the SCO + public Element raw; + + // The minimum score that the student could have achieved + public Element min; + + // The maxium score or total number that the student could have achieved + public Element max; + + + /**************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: Default constructor for the CMIScore + ** + ****************************************************************************/ + public CMIScore() + { + // Set up default values for all attributes + + super( true ); + raw = new Element("","checkScoreDecimal","NULL",true,true,true); + min = new Element("","checkScoreDecimal","NULL",true,true,true); + max = new Element("","checkScoreDecimal","NULL",true,true,true); + } + + + /************************************************************************ + ** Accessers to the CMIScore Data. SCOs should not call these methods. + ** SCOs should call LMSGetValue() + ************************************************************************/ + public Element getRaw() + { + return raw; + } + public Element getMin() + { + return min; + } + public Element getMax() + { + return max; + } + + /************************************************************************ + ** Modifiers to the CMIScore Data. SCOs should not call these methods. + ** SCOs should call LMSSetValue() + ************************************************************************/ + public void setRaw(String inRaw) + { + raw.setValue(inRaw); + } + public void setMin(String inMin) + { + min.setValue(inMin); + } + public void setMax(String inMax) + { + max.setValue(inMax); + } + + public boolean isInitialized() + { + boolean flag = false; + if ( (raw.isInitialized() || + min.isInitialized() || + max.isInitialized() ) ) + { + flag = true; + } + + return flag; + } + + /**************************************************************************** + ** + ** Method: isValidRequest + ** Input: CMIRequest theRequest - The tokenized request + ** + ** Output: boolean flag indicating whether or not the request is + ** a valid request. + ** + ** Description: This method determins if the request is a valid + ** CMI request. + ** + ***************************************************************************/ + public boolean isValidRequest(CMIRequest theRequest) + { + boolean flag = false; + String token = theRequest.getNextToken(); + + if ( token.equals("_children") ) + { + flag = true; + } + else if ( (token.equals("raw") ) || + (token.equals("min") ) || + (token.equals("max") ) ) + { + flag = true; + if (theRequest.hasMoreTokensToProcess() ) + { + if ( theRequest.isAChildrenRequest() ) + { + flag = true; + } + else + { + flag = false; + } + } + } + return flag; + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - The tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the LMSGetValue() request. The method + ** determines the value for the requested data element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Resultant value to return + String result = new String(""); + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // *** There are no more subcategories in the CMI Score class + // *** Since there are more tokens to process, the data model + // *** element was not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + token + + "is not a valid element of the CMI Score\n" + + "Data Model Category"); + } + + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + + } + else + { + // No more tokes to process + + if ( theRequest.isAChildrenRequest() ) + { + result = getChildren(); + dmErrorMgr.SetCurrentErrorCode("0"); + } + else + { + // determine the value associated with the element requested + result = determineElementValue(this,token,dmErrorMgr); + } + } + return result; + } + + + /**************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String - string representation of the attributes + ** + ** Description: This method returns the attributes of the class in + ** string format. + ** + ***************************************************************************/ + public String getChildren() + { + String children = "raw,min,max"; + + return children; + } + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - The tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** Output: none + ** + ** Description: This method performs the LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Get the next token off of the request + // raw, max, or min + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // More tokens to process -- Error + + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + token + + "is not a valid element of the CMI Score\n" + + "Data Model Category"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + // No more tokens to process + + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + if ( theRequest.isAKeywordRequest() == false ) + { + // Set the value + doSet(this,token,value,dmErrorMgr); + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element is not writeable + // *** Trying to set the _children element. + System.out.println("Error - Cannot Set Data Model Element"); + System.out.println("Element being processed: " + token + + "cannot be set\n"); + } + + // Notify error manager + dmErrorMgr.recKeyWordError(token); + + } + } + } // end of performSet + +} // end of CMIScore Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentData.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentData.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentData.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,339 @@ +/******************************************************************************* +** +** Filename: CMIStudentData.java +** +** File Description: The CMIStudentData class manages information to support +** customization of an SCO based on a +** student's performance. +** +** Author: ADL Technical Team +** +** Contract Number: +** Company Name: CTC +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 08/07/2000 ADLI Team Made the attempt_record and tries attributes +** public. In order for the Java Reflection +** API to function correctly, these attributes +** had to be public. +** +** 10/31/2000 R. Ball PT 295: SCORM 1.1 Changes from Slash-n-Burn +** All elements were removed except for: +** mastery_score, max_time_allowed, and +** time_limit_action. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIStudentData extends CMICategory +implements Serializable +{ + // The passing score, as determined outside the SCO + public Element mastery_score; + + // The amount of time the student is allowed to have in the current + // attempt of the SCO + public Element max_time_allowed; + + // What the SCO is to do when the max time allowed is exceeded + public Element time_limit_action; + + private static int CMISTUD_DATA_MIN_NUM_TOKENS = 3; + + /************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: The default constructor sets up the class and initalizes + ** all of its attributes + ** Parameters passed into Element: + ** ,,,, + ** + ** See Element Constructor for more detail + **************************************************************************/ + public CMIStudentData() + { + // Set up default values for all attributes + super( true ); + mastery_score = new Element("","checkDecimal","NULL",false,true,false); + max_time_allowed = + new Element("","checkTimespan","NULL",false,true,false); + time_limit_action = new Element("","checkVocabulary","TimeLimitAction", + false,true,false); + + } // end of defaul constructor + + /************************************************************************ + ** Accessers to the CMIStudentData Data. AUs should not call these + ** methods. AUs should call LMSGetValue() + ************************************************************************/ + public Element getMasteryScore() + { + return mastery_score; + } + public Element getMaxTimeAllowed() + { + return max_time_allowed; + } + public Element getTimeLimitAction() + { + return time_limit_action; + } + + /************************************************************************ + ** Modifiers to the CMIStudentData Data. AUs should not call these + ** methods. AUs should call LMSSetValue(). + ************************************************************************/ + public void setMasteryScore(String inMasteryScore) + { + mastery_score.setValue(inMasteryScore); + } + public void setMaxTimeAllowed(String inMaxTimeAllowed) + { + max_time_allowed.setValue(inMaxTimeAllowed); + } + public void setTimeLimitAction(String inTimeLimitAction) + { + time_limit_action.setValue(inTimeLimitAction); + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the LMSGetValue() request. The method + ** determines the value for the requested data element. The method + ** handles the cases where there are additional sub-classes + ** (subcategories) for the CMIStudent Data element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Resultant value to return + String result = new String(""); + + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // *** There are no more subcategories in the CMI Score class + // *** Since there are more tokens to process, the data model + // *** element was not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + token + + "is not a valid element of the CMI Student Data\n" + + "Data Model Category"); + } + + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + + } + else + { + // No more tokes to process + + if ( theRequest.isAChildrenRequest() ) + { + result = getChildren(); + } + else + { + // determine the value associated with the element requested + result = determineElementValue(this,token,dmErrorMgr); + } + } + return result; + } + + + + /**************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** Output: String + ** + ** Description: + ** This method returns a String containing the list of data elements that + ** CMI Score data object contains. + ** + ***************************************************************************/ + public String getChildren() + { + String children = "mastery_score,max_time_allowed,time_limit_action"; + + return children; + } + + /*************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs all of the necessary steps to process + ** an LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Get the next token off of the request + // raw, max, or min + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // More tokens to process -- Error + + // Error - Data Model Element not implemented + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Element being processed: " + token + + "is not a valid element of the CMI Score\n" + + "Data Model Category"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + // No more tokens to process + + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + if ( theRequest.isAKeywordRequest() == false ) + { + // Set the value + doSet(this,token,value,dmErrorMgr); + } + else + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element is not writeable + // *** Trying to set the _children element. + System.out.println("Error - Cannot Set Data Model Element"); + System.out.println("Element being processed: " + token + + "cannot be set\n"); + } + + // Notify error manager + dmErrorMgr.recKeyWordError(token); + + } + } + } // end of performSet + + /*************************************************************************** + ** + ** Method: isValidStudDataRequest + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** + ** Output: Boolean value indicating whether or not the StudentData Request + ** is valid. + ** + ** Description: Checks to make sure that the request meets the minimum + ** requirements needed for a CMIStudentData Model Element. + ** + **************************************************************************/ + private boolean isValidStudDataRequest(CMIRequest theRequest) + { + boolean rtrnFlag = false; + + if(theRequest.isForASetRequest()) + { + if((theRequest.getTotalNumTokens() - 1) >= + CMISTUD_DATA_MIN_NUM_TOKENS) + { + rtrnFlag = true; + } + } + else + { + if(theRequest.getTotalNumTokens() >= CMISTUD_DATA_MIN_NUM_TOKENS) + { + rtrnFlag = true; + } + } + + return rtrnFlag; + + } // end of isValidStudDataRequest() + +} // end of CMIStudentData Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentPreference.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentPreference.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMIStudentPreference.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,411 @@ +/******************************************************************************* +** +** Filename: CMIStudentPreference.java +** +** File Description: The CMIStudentPreference class manages student selected +** options that are appropriate for subsequent Assignable +** Units. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 09/05/2000 ADLI Project PT110 : Any references to CMIString256 were +** changed to CMIString255 to reflect +** the changes in the CMI 3.0.3 +** document. +** +** 09/07/2000 ADLI Project PT112 : The "language" element was changed +** to CMIString255 due to the fact that +** CMILocale no longer exists. +** +** 11/15/2000 S. Thropp PT 296: Removal of all elements except for +** audio,language, speed, and text. +** +** 05/14/2002 B. Capone PT1912: Modified performSet() - needed to +** restrict the allowable range of values for +** audio, speed and text. +** +*********************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMIStudentPreference extends CMICategory + implements Serializable + +{ + // Sound on/off and volume control + public Element audio; + + // Identifies in what language the information should be delivered + public Element language; + + // Pace of content delivery + public Element speed; + + // Written content visibility control + public Element text; + + // The minimum number of tokens in a valid Student Preference Data Model + // Element request + static int CMISTPREF_MIN_NUM_TOKENS = 3; + + /************************************************************************** + ** + ** Method: Default constructor + ** Input: none + ** Output: none + ** + ** Description: The default constructor sets up the class and initalizes + ** all of its attributes + ** + **************************************************************************/ + public CMIStudentPreference() + { + // Set up default values for all attributes + super( true ); + audio = new Element("","checkSInteger","NULL",true,true,true); + language = new Element("","checkString255","NULL",true,true,true); + speed = new Element("","checkSInteger","NULL",true,true,true); + text = new Element("","checkSInteger","NULL",true,true,true); + + } // end of default constructor + + /************************************************************************ + ** Accessers to the CMIStudentPreference Data. AUs should not call + ** these methods. AUs should call LMSGetValue(). + ************************************************************************/ + public Element getAudio() + { + return audio; + } + public Element getLanguage() + { + return language; + } + public Element getSpeed() + { + return speed; + } + public Element getText() + { + return text; + } + + /************************************************************************ + ** Modifiers to the CMIStudentPreference Data. AUs should not call + ** these methods. AUs should call LMSSetValue() + ************************************************************************/ + public void setAudio(String inAudio) + { + audio.setValue(inAudio); + } + public void setLanguage(String inLanguage) + { + language.setValue(inLanguage); + } + public void setSpeed(String inSpeed) + { + speed.setValue(inSpeed); + } + public void setText(String inText) + { + text.setValue(inText); + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the LMSGetValue() request. The method + ** determines the value for the requested data element. The method + ** handles the cases where there are additional sub-classes + ** (subcategories) for the CMICoreData data element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Resultant value to return + String result = new String(""); + + // Check to make sure this is a valid LMSGetValue() request + if ( isValidStPrefRequest(theRequest) == true ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to interface"); + } + + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + } + else + { + // No more tokes to process + + // Check to see if the request is for the children of Core Data + if ( theRequest.isAChildrenRequest() ) + { + // Set result to the string of children + result = getChildren(); + } + else + { + // determine the value associated with the element requested + result = determineElementValue(this,token,dmErrorMgr); + } + } // end of ifHasMoreTokens() + } // end of isVaildStPrefRequest + else + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to interface"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done getting requested element. Let the Request object know + // that processing of the LMSGetValue() request is done + theRequest.done(); + + return result; + } // end of performGet() + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest theRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs all of the necessary steps to process + ** an LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Check to see if this is a valid LMSSetValue() request + if ( isValidStPrefRequest(theRequest) == true ) + { + // Get the next token off of the request + String token = theRequest.getNextToken(); + + // Check to see if the request has any more tokens to + // process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSGetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to interface"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + // No more tokens to process + if ( theRequest.isAChildrenRequest() ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Error - trying to set a keyword"); + } + dmErrorMgr.recKeyWordError(token); + } + else + { + // Get the value to use for setting off of the request + String value = theRequest.getValue(); + + //Special cases for audio, speed and text + if (token.equals("audio") || token.equals("speed") || + token.equals("text")) + { + try + { + int ivalue; + ivalue = Integer.parseInt(value); + if ((token.equals("audio") && ((ivalue >= -1) + && (ivalue <= 100))) || + (token.equals("speed") && ((ivalue >= -100) + && (ivalue <= 100))) || + (token.equals("text") && ((ivalue >= -1) + && (ivalue <= 1)))) + { + // Set the value + doSet(this,token,value,dmErrorMgr); + } + else + { + dmErrorMgr.SetCurrentErrorCode("405"); + } + } + catch(NumberFormatException nfe) + { + dmErrorMgr.SetCurrentErrorCode("405"); + if ( DebugIndicator.ON ) + { + System.out.println("Error - Number Format Exception"); + } + } + } + else + { + // For all others, Set the value + doSet(this,token,value,dmErrorMgr); + } + } + } + } + else + { + if ( DebugIndicator.ON ) + { + // Invalid parameter passed to LMSSetValue() + System.out.println("Error - Data Model Element not implemented"); + System.out.println("Invalid data model element: " + + theRequest.getRequest() + + " passed to interface"); + } + // Notify error manager + dmErrorMgr.recNotImplementedError(theRequest); + } + + // Done getting requested element. Let the Request object know + // that processing of the LMSGetValue() request is done + theRequest.done(); + + return; + + } // end of performSet() + + + /**************************************************************************** + ** + ** Method: isValidStPrefRequest + ** Input: CMIRequest theRequest - the LMSGetValue() request + ** + ** Output: Boolean value indicating whether or not the Student Preference + ** Request is valid. + ** + ** Description: Checks to make sure that the request meets the minimum + ** requirements needed for a CMIStudentPreferenceData Model + ** Element. + ** + ***************************************************************************/ + private boolean isValidStPrefRequest(CMIRequest theRequest) + { + boolean rtrnFlag = false; + + if ( theRequest.getTotalNumTokens() >= CMISTPREF_MIN_NUM_TOKENS ) + { + rtrnFlag = true; + } + + return rtrnFlag; + + } // end of isValidStPrefRequest() + + /**************************************************************************** + ** + ** Method: getChildren + ** Input: none + ** + ** Output: String representation of the children (attributes) of the + ** CMIStudentPreference Data Model Category + ** + ** Description: Returns a String representation of the children of the + ** CMIStudentPreference + ** + ***************************************************************************/ + private String getChildren() + { + String children = new String("audio,language,speed,text,"); + + return children; + } // end of getChildren() + +} // end of StudentPreference Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMISuspendData.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMISuspendData.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMISuspendData.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,232 @@ +/******************************************************************************* +** +** Filename: CMISuspendData.java +** +** File Description: The CMISuspendData class manages unique information +** generated by the SCO during previous uses, +** that is needed for the current use. +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** In order to use Reflection (Java Feature) the defined Java +** coding standards are NOT being followed. Reflection requires +** field names to match identically to input parameter. The +** attribute names match what is expected from a LMSGetValue() +** or LMSSetValue() request. Also the attribute values are declared +** as public scope in order to use reflection. +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 263: Removal of reference to version of +** SCORM. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class CMISuspendData extends CMICategory + implements Serializable +{ + // Unique information generated by the SCO during previous + // uses, that is needed for the current use + public Element suspend_data; + + /**************************************************************************** + ** + ** Method: Constructor + ** Input: String suspendData - Unique information generated by the AU + ** during previous uses, that is needed + ** for the current use. + ** Output: none + ** + ** Description: Sets up the CMI Suspend Data using the string passed in + ** + ***************************************************************************/ + public CMISuspendData(String suspendData) + { + + super( true ); + suspend_data = new Element (suspendData,"checkString4096","NULL", + true,true,true); + + } // end of constructor + + /**************************************************************************** + ** + ** Method: Default Constructor + ** Input: none + ** Output: none + ** + ** Description: Sets up a default value for the suspend_data attribute. + ** Marks the element as mandatory,readable and writeable + ** + ***************************************************************************/ + public CMISuspendData() + { + + super( true ); + + suspend_data = new Element("","checkString4096","NULL", + true,true,true); + + } // end of default constructor + + /************************************************************************ + ** Accessers to the CMISuspendData Data. AUs should not call these + ** methods. The AUs should call LMSGetValue() + ************************************************************************/ + public Element getSuspendData() + { + return suspend_data; + } + + /************************************************************************ + ** Modifiers to the CMISuspendData Data. AUs should not call these + ** methods. The AUs should call LMSSetValue() + ************************************************************************/ + public void setSuspendData(String inSuspendData) + { + suspend_data.setValue(inSuspendData); + } + + /**************************************************************************** + ** + ** Method: performGet + ** Input: CMIRequest theRequest - the tokenized LMSGetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: String - the value portion of the element for the LMSGetValue() + ** + ** Description: This method performs the necessary steps to retrieve the + ** value for the suspend_data data model element. + ** + ***************************************************************************/ + public String performGet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // String to hold the value of the final element + String result = new String(""); + + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // No more elements should exist + System.out.println("Error - Data Model Element not implemented\n"); + System.out.println("Element being processed: " + + theRequest.getRequest() + + "element of the CMI Suspend Data " + + "Data Model Category"); + } + // Determine if the Request is for a keyword. + if ( theRequest.isAKeywordRequest() ) + { + dmErrorMgr.recGetKeyWordError(theRequest.getElement()); + } + else + { + dmErrorMgr.recNotImplementedError(theRequest); + } + + } + else + { + // No more tokes to process + + // determine the value associated with the element requested + result = suspend_data.getValue(); + } + + // Done getting requested element. Let the CMIRequest object + // know that processing of the LMSGetValue() is done + theRequest.done(); + + return result; + } // end of performGet + + /**************************************************************************** + ** + ** Method: performSet + ** Input: CMIRequest getRequest - tokenized LMSSetValue() request + ** DMErrorManager dmErrorMgr - Error manager + ** + ** Output: none + ** + ** Description: This method performs the necessary steps to process + ** an LMSSetValue() request. + ** + ***************************************************************************/ + public void performSet(CMIRequest theRequest, + DMErrorManager dmErrorMgr) + { + // Check to see if the Request has more tokens to process + if ( theRequest.hasMoreTokensToProcess() ) + { + if ( DebugIndicator.ON ) + { + // Error - Data Model Element not implemented + // No more elements should exist + System.out.println("Error - Data Model Element not implemented\n"); + System.out.println("Element being processed: " + + theRequest.getRequest() + + "element of the CMI Suspend Data " + + "Data Model Category"); + } + + dmErrorMgr.recNotImplementedError(theRequest); + } + else + { + // perform the actual set + doSet(this,"suspend_data",theRequest.getValue(),dmErrorMgr); + } + + // Done setting requested element. Let the CMIRequest object + // know that processing of the LMSSetValue() is done + theRequest.done(); + + } // end of performSet() + +} // end of CMISuspendData Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMITime.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMITime.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/CMITime.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,228 @@ +/******************************************************************************* +** +** Filename: CMITime.java +** +** File Description: The CMITime class manages timing information for +** use in the Data Model. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee does +** not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE POSSIBILITY +** OF SUCH DAMAGES. +******************************************************************************* +** +** Date Changed Author of Change Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 263: Removal of reference to a version +** of SCORM. +** +** 07/06/2001 Jeff Falls Related to PT 964: Made the "add()" and +** "toString()" functions more robust to handle +** maintenance of the proper format: +** hh:mm:ss.ss +** +** 03/12/2002 Bill Capone PT 1822: Modified toString(), the seconds +** portion. Also, added accessors and modifiers +** for CMIHours, CMIMinutes and CMISeconds. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.io.*; +import java.util.*; +import java.lang.Integer; + +//adl imports +import java.lang.Float; +import org.adl.datamodels.*; + +public class CMITime implements Serializable +{ + private int CMIHours; + private int CMIMinutes; + private float CMISeconds; + + + /*************************************************************************** + ** + ** Method: constructor + ** Input: String timeString + ** Output: none + ** + ** Description: + ** This constructor takes as input a string that should be in the form of + ** HH:MM:SS.S and create a CMITime object. + ** For this example code error checking is not being done to ensure that the + ** string is in the correct format. + ** + ***************************************************************************/ + public CMITime( String timeString ) + { + StringTokenizer st = new StringTokenizer( timeString, ":" ); + String lmsHours = st.nextToken(); + String lmsMinutes = st.nextToken(); + String lmsSeconds = st.nextToken(); + + CMIHours = Integer.parseInt( lmsHours ); + CMIMinutes = Integer.parseInt( lmsMinutes ); + CMISeconds = Float.valueOf( lmsSeconds ).floatValue(); + //CMISeconds = Float.parseFloat( lmsSeconds ); + } + + /************************************************************************ + ** Accessors to the CMITime Data. + ************************************************************************/ + public int getHours() + { + return CMIHours; + } + public int getMinutes() + { + return CMIMinutes; + } + public float getSeconds() + { + return CMISeconds; + } + + /************************************************************************ + ** Modifiers to the CMITime Data. + ************************************************************************/ + public void setHours(int iHours) + { + CMIHours = iHours; + } + public void setMinutes(int iMinutes) + { + CMIMinutes = iMinutes; + } + public void setSeconds(float iSeconds) + { + CMISeconds = iSeconds; + } + + /*************************************************************************** + ** + ** Method: toString + ** Input: none + ** Output: String representation of time + ** + ** Description: + ** This method will return the time as a String. The format of the time will be + ** hh:mm:ss.SS + ** + ***************************************************************************/ + public String toString() + { + String temp = new String("0"); + + String hours = Integer.toString( CMIHours, 10 ); + + if ( hours.length() == 1 ) + { + hours = "0" + hours; + } + else if ( hours.length() == 0 ) + { + hours = "00"; + } + + String minutes = Integer.toString( CMIMinutes, 10 ); + + if ( minutes.length() == 1 ) + { + minutes = "0" + minutes; + } + else if ( minutes.length() == 0 ) + { + minutes = "00"; + } + + String seconds = Float.toString( CMISeconds ); + + if ( seconds.length() == 1 ) + { + seconds = "0" + seconds; + } + else if ( seconds.length() == 0 ) + { + seconds = "00"; + } + + return hours + ":" + minutes + ":" + seconds; + } + + /*************************************************************************** + ** + ** Method: add + ** Input: CMITime addTime - time to add to this time + ** Output: none + ** + ** Description: + ** This method will add the time represented by the addTime input parameter to + ** the time represented by 'this' CMITime object. The new time will be stored + ** back into 'this' CMITime object. + ** + ***************************************************************************/ + public void add( CMITime addTime ) + { + int newHours = 0; + int newMinutes = 0; + float newSeconds = (float)0.0; + + // Add the time together + newSeconds = CMISeconds + addTime.CMISeconds; + if ( newSeconds > 60.0 ) + { + newSeconds = newSeconds - (float)60.0; + newMinutes = newMinutes + 1; + } + // ensure that seconds is in the following format: ss.ss + newSeconds = (float)((int)(newSeconds * 100)) / (float)100.00; + + newMinutes = newMinutes + CMIMinutes + addTime.CMIMinutes; + if ( newMinutes > 60 ) + { + newMinutes = newMinutes - 60; + newHours = newHours + 1; + } + newHours = newHours + CMIHours + addTime.CMIHours; + + // Store off the new time back into the lms core data + CMIHours = newHours; + CMIMinutes = newMinutes; + CMISeconds = newSeconds; + } + +} Index: openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/DMErrorManager.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/DMErrorManager.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/datamodels/cmi/DMErrorManager.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,376 @@ +/******************************************************************************* +** +** Filename: DMErrorManager.java +** +** File Description: This class implements the error handling capabilities +** of the Data Model. It manages the error codes set by +** any data model class. +** +** Author: ADLI Project +** +** Company Name: Concurrent Technologies Corporation +** +** Module/Package Name: org.adl.datamodel.cmi +** Module/Package Description: Collection of CMI Data Model objects +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: AICC CMI Data Model +** ADL SCORM +** +******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** doesnot utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGES. +** +******************************************************************************* +** +** Date Changed Author Reason for Changes +** ------------ ---------------- ------------------------------------------- +** 11/15/2000 S. Thropp PT 292: Clean up of error codes to match +** changes to CMI001 revision 3.4 +** +** 12/28/2000 J. Poltrack PT 292: Mapped the error code descriptions +** to the descriptions in SCORM 1.1 +** +** 08/27/2001 J. Falls 1) Changed "can not" to "cannot". +** 2) Changed "key word" to "keyword". +** +** 03/20/2002 B. Capone Removed the "void" from the Constructor. +** +*******************************************************************************/ +package org.adl.datamodels.cmi; + +//native java imports +import java.lang.*; + +//adl imports +import org.adl.util.debug.*; +import org.adl.datamodels.*; + +public class DMErrorManager +{ + + private static String currentErrorCode; + + private static String[][] errors = + { + {"0", "No Error", + "The previous LMS API Function call completed successfully."}, + {"101", "General Exception", + "An unspecified, unexpected exception has occurred."}, + {"201", "Invalid argument error", ""}, + {"202", "Element cannot have children", ""}, + {"203", "Element not an array - cannot have count", ""}, + {"301", "Not initialized", "The LMS is not initialized."}, + {"401", "Not implemented error", + "The data model element in question was not implemented."}, + {"402", "Invalid set value, element is a keyword", + "Trying to set a reserved keyword in the data model. " + + "Trying to set a keyword (_count, _children, or _version). " + + "This is prohibited."}, + {"403", "Element is read only", + "Data Element is Read Only (Not Writeable). "+ + "Cannot call LMSSetValue() for the element in question."}, + {"404", "Element is write only", + "Data Element is Write Only (Not Readable). "+ + "Cannot call LMSGetValue() for the element in question."}, + {"405", "Incorrect Data Type", + "Invalid Type being used for setting element. "+ + "The type being used as the set value argument does not match" + + " that of the element being set." } + }; + + /***************************************************************************** + ** + ** Method: DMErrorManager() + ** Input: none + ** Output: none + ** + ** Description: + ** Default Constructor - intializes the current error code to "No Error". + ** + *****************************************************************************/ + public DMErrorManager() + { + currentErrorCode = "0"; + } + + /***************************************************************************** + ** + ** Method: recNotImplementedError() + ** Input: CMIRequest theRequest: the request being processed + ** Output: none + ** + ** Description: + ** Records the appropriate Not Implemented error + *****************************************************************************/ + public void recNotImplementedError(CMIRequest theRequest) + { + if ( theRequest.isAChildrenRequest() ) + { + if ( DebugIndicator.ON ) + { + System.out.println( + "Trying to get/set an _children element.\n This" + + " keyword is not permitted to be implemented on" + + " the given element"); + } + + SetCurrentErrorCode("401"); + } + else if ( theRequest.isACountRequest() ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to get/set an _count element.\n This" + + " keyword is not permitted to be implemented on" + + " the given element"); + } + SetCurrentErrorCode("401"); + } + else + { + // Notify error manager + SetCurrentErrorCode("401"); + } + + } + + /***************************************************************************** + ** + ** Method: recKeyWordError() + ** Input: String inElement: element being processed + ** Output: none + ** + ** Description: + ** Determines which keyword (_children, _count, _version) is being processed + ** and sets the correct error code + ** + *****************************************************************************/ + public void recKeyWordError(String inElement) + { + if ( inElement.equals("_children") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to set an _children element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("402"); + } + else if ( inElement.equals("_count") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to set an _count element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("402"); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to set an _version element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("402"); + } + + } + + /***************************************************************************** + ** + ** Method: recGetKeyWordError() + ** Input: String inElement: element being processed + ** Output: none + ** + ** Description: + ** Determines which keyword (_children, _count, _version) is being processed + ** and sets the correct error code + ** + *****************************************************************************/ + public void recGetKeyWordError(String inElement) + { + if ( inElement.equals("_children") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to get an _children element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("202"); + } + else if ( inElement.equals("_count") ) + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to get an _count element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("203"); + } + else + { + if ( DebugIndicator.ON ) + { + System.out.println("Trying to get an _version element. This" + + " action is not permitted!"); + } + SetCurrentErrorCode("401"); + } + + } + + /***************************************************************************** + ** + ** Method: GetCurrentErrorCode() + ** Input: none + ** Output: String - current error code + ** + ** Description: + ** Returns the value of the Current Error Code that was set by the most + ** recent API call. + ** + *****************************************************************************/ + public String GetCurrentErrorCode() + { + return currentErrorCode; + } + + /***************************************************************************** + ** + ** Method: SetCurrentErrorCode(String code) + ** Input: String code - The error code (from the predefined list of codes) + ** Output: none + ** + ** Description: + ** Sets the value of the Current Error Code. + ** + *****************************************************************************/ + public void SetCurrentErrorCode(String code) + { + currentErrorCode = code; + } + + /***************************************************************************** + ** + ** Method: ClearCurrentErrorCode() + ** Input: none + ** Output: none + ** + ** Description: + ** Sets the value of the Current Error Code to "No Error". + ** + *****************************************************************************/ + public void ClearCurrentErrorCode() + { + currentErrorCode = errors[0][0]; + } + + + /***************************************************************************** + ** + ** Method: GetErrorDescription(String code) + ** Input: String code - error code + ** Output: String - the description associated with the given error code + ** + ** Description: + ** Retrieves and returns the text associated with the given error code + ** + *****************************************************************************/ + public String GetErrorDescription(String code) + { + // retrieves and returns the description of the provided error code + return GetErrorElement(code)[1]; + } + + /***************************************************************************** + ** + ** Method: GetErrorDiagnostic(String code) + ** Input: String code - error code + ** Output: String - the diagnostic text associated with the given error code + ** + ** Description: + ** Retrieves and returns the diagnostic text associated with the error code + ** + *****************************************************************************/ + public String GetErrorDiagnostic( String code ) + { + return GetErrorElement(code)[2]; + } + + /***************************************************************************** + ** + ** Method: GetErrorElement(String code) + ** Input: String code - error code + ** Output: String[] - the array corresponding to the element identified by + ** the given error code + ** + ** Description: + ** Private function that gets the array containing the error element info + ** identified by the given error code + ** + *****************************************************************************/ + private String[] GetErrorElement(String code) + { + for ( int i=0; i0 ) { + this.servletURL = + new URL(protocol + "://" + host + ":" + port + path ); + } else { + this.servletURL = + new URL(protocol + "://" + host + path ); + } + + System.out.println("servlet url is "+ this.servletURL.toString()); + + //String session = getCookie("ad_session_id"); + //System.out.println("session is: " + session); + if ( _Debug ) { + System.out.println("servlet host "+ host.toString()); + System.out.println("servlet port "+ port); +// tfield.setText("----inited inited inited"); + } + } + catch ( Exception e ) + { + e.printStackTrace(); + stop(); // we shouldn't proceed if we catch an exception here... + } + + + } + + + /***************************************************************************** + ** + ** Method: getAppletInfo + ** Input: none + ** Output: String containing the information about the API applet class + ** + ** Description: + ** The applet getAppletInfo method + ** + *****************************************************************************/ + public String getAppletInfo() + { + return "RTE API Implementation. Michele Slocovich for SII and .LRN community. Based on:\n" + + "Sample RTE API Implementation \nAuthor: R. Ball, CTC \n" + + "Example of one possible LMS API Implementation."; + } + + public void destroy() + { + + if ( _Debug ) + { + // this.setBackground(new Color(0xFFFFFF)); // Set background color to blue. + // this.setForeground(Color.white); // Set foreground color to white. + } + + System.out.println("begin destroy"); + this.theSCOData=null; + // this.tfield=null; + // this.efield=null; + System.out.println("within destroy"); + return ; + } + + public void finalize(){ + //destroy(); + System.out.println("begin finalize"); + System.out.println("within finalize"); + return; + } + + + public void stop() + { + System.out.println("begin stop"); + System.out.println("within stop"); + return ; + } + /***************************************************************************** + ** + ** Method: getParameterInfo + ** Input: none + ** Output: String[][] + ** + ** Description: + ** The applet getParameterInfo method + ** + *****************************************************************************/ + public String[][] getParameterInfo() + { + String[][] info = { + {"None", "", "This applet requires no parameters."}}; + return info; + } + + /***************************************************************************** + ** + ** Method: CheckInitialization + ** Input: none + ** Output: boolean + ** + ** Description: + ** determin + ** + *****************************************************************************/ + private boolean CheckInitialization() + { + if ( isLMSInitialized != true ) + { + this.lmsErrorManager.SetCurrentErrorCode("301"); + } + + return isLMSInitialized; + } + + /*************************************************************************** + ** + ** Method: LMSInitialize(String param) + ** Input: String param - must be null string - reserved for future use + ** Output: CMIBoolean "false" if fails, "true" if succeeds + ** + ** Description: + ** The applet init method + ** + ***************************************************************************/ + + public String LMSInitialize(String param) + { + // This function must be called by a SCO before any other API calls are made. It can not be called more than once consecutively unless LMSFinish is called. + if ( _Debug ) + { + // tfield.setText("----INITIALIZING---CALL FROM JAVASCRIPT RECEIVED"); + System.out.println("*********************"); + System.out.println("In API::LMSInitialize"); + System.out.println("*********************"); + System.out.println(""); + // efield.setText(""); + } + String result = cmiBooleanFalse; // assume failure + // Make sure param is empty string "" - as per the API spec + // Check for "null" is a workaround described in "Known Problems" in the header. + String tempParm = String.valueOf(param); + if ( (tempParm.equals("null") || tempParm.equals("")) != true ) + { + APIAdapterApplet.lmsErrorManager.SetCurrentErrorCode("201"); + return result; + } + // Is LMS already initialized? + if ( APIAdapterApplet.isLMSInitialized == true ) { + if ( _Debug ) { + System.out.println("********************************************"); + System.out.println("LMS seems have been already INITIALIZED"); + System.out.println("********************************************"); + // tfield.setText("----ALREADY INITED"); + } + APIAdapterApplet.lmsErrorManager.SetCurrentErrorCode("101"); + result = cmiBooleanFalse; // NO success (see return at the end + } else { + if ( _Debug ) { System.out.println("Trying to get SCO Data from servlet..."); } + // Build the local (client-side) LMS data model cache by getting the SCODataManager class instances from the LMS Servlet + ServletProxy servletProxy = new ServletProxy(this.servletURL, this.cookie); + String DataFromServer = servletProxy.GetSCOData(); + if(DataFromServer.startsWith("ERROR")) { + APIAdapterApplet.isLMSInitialized=false; + APIAdapterApplet.lmsErrorManager.SetCurrentErrorCode("201"); + System.out.println( "Error on server on during communication" ); + this.LastServerError=DataFromServer; //store this for javascript to know + result = cmiBooleanFalse; //no success + return result; //tell about no success to caller + } + + if ( _Debug ) { System.out.println("In LMSInitialize : Data obtained from server --> "+DataFromServer); } + //PARSING RESULT - we must PARSE RESULT AND CALL CORRESPONDING SETTINGS for each couple of values do a LMSSetValue + try { + // FIRST WE INITIALIZE AN EMPTY SCODATAMANAGER + SCODataManager SCOData = new SCODataManager(); + APIAdapterApplet.theSCOData = SCOData; + System.out.println("In LMSInitialize : CREATED EMPTY DATA" ); + // HERE WE STATE THING IS INITIALIZED - WITHIN CATCH WE SHOULD DE-INITIALIZE NECESSARY FOR SETVALUE TO WORK + APIAdapterApplet.isLMSInitialized = true; + System.out.println("In LMSInitialize : now parsing server data" ); + //String[] couples = DataFromServer.split(","); + Pattern p=Pattern.compile("^([^=]+)=(.*)$"); + DataFromServer=","+DataFromServer; + String[] couples = DataFromServer.split(",cmi\\."); + int howmany = couples.length; + System.out.println("In LMSInitialize, we have : " + howmany + " couples "); + //note we start from first couple since zeroest is null + for ( int z = 1 ; z< howmany; z++) { + String Element=""; + String Value=""; + Matcher m=p.matcher(couples[z]); + //zeroth split with regex grouping is the whole string + if(m.find()) { + Element=m.group(1); + Value=m.group(2); + } else { + System.out.println("PARSE ERROR WITHIN:"); + System.out.println( "Couple is " + couples[z] ); + } + //String Element = p.split(couples[z])[1]; + if(z>0) { Element="cmi."+Element; } + //String Value=""; + //try {Value = p.split(couples[z])[2];} + //catch (Exception parser) {Value="";} + if(_Debug) { System.out.println( "Couple is " + couples[z] ); + System.out.println( "setting element " + Element ); + System.out.println( "to value " + Value ); } + + if( Value.length()>0 ) { + APIAdapterApplet.areweloading=true; + if(_Debug) { System.out.println("LMSSetValue returns " + LMSSetValue(Element,Value)); + } else { + LMSSetValue(Element,Value); + } + APIAdapterApplet.areweloading=false; + } else { + System.out.println("Received a null value from server: not setting"+Element); + } + } + } catch(Exception parsing) { + APIAdapterApplet.isLMSInitialized=false; + APIAdapterApplet.lmsErrorManager.SetCurrentErrorCode("201"); + if(_Debug) { + System.out.println( "Error while parsing from server" ); + parsing.printStackTrace(); } + result = cmiBooleanFalse; //no success + return result; //tell about no success to caller + } + System.out.println("In LMSInitialize : server data parsed" ); + if ( _Debug ) + { System.out.println("The Core Data for the current SCO contains the following:"); + theSCOData.getCore().showData(); } + + // No errors were detected + APIAdapterApplet.lmsErrorManager.ClearCurrentErrorCode(); + result = cmiBooleanTrue; // success + } + + if ( _Debug ) + { + // tfield.setText("----LMSInitialized OK LMSInitialized"); + System.out.println(""); + System.out.println("********************************************"); + System.out.println("Done Processing LMSInitialize() WITH SUCCESS"); + System.out.println("********************************************"); + System.out.println(" returning "+result); + } + return result; + } + + public String getCookie(String cookieName) + { + String cookie=null; + System.out.println("within getcookie function"); + return cookie; + } + + + /*************************************************************************** + ** + ** Method: LMSFinish + ** Input: none + ** Output: none + ** + ** Description: + ** Signals completion of communication with LMS + ** + ***************************************************************************/ + public String LMSFinish(String param) + { + if ( _Debug ) + { + System.out.println("*****************"); + System.out.println("In API::LMSFinish"); + System.out.println("*****************"); + System.out.println(""); + // tfield.setText("----ENTERED FINISH"); + } + // efield.setText(""); + + String result = cmiBooleanFalse; // assume failure + + // Make sure param is empty string "" - as per the API spec + // Check for "null" is a workaround described in "Known Problems" + // in the header. + String tempParm = String.valueOf(param); + if ( (tempParm.equals("null")) || (tempParm.equals("")) ) + { + if ( CheckInitialization() == true ) + { + CMICore lmsCore = this.theSCOData.getCore(); + + // Need to add the SCOs Session Time into the running total time + CMITime totalTime = new CMITime( lmsCore.getTotalTime().getValue() ); + + if(_Debug) + { System.out.println("\tTotal time: " + totalTime.toString()); } + + CMITime sessionTime = new CMITime( lmsCore.getSessionTime().getValue() ); + + if(_Debug) + { System.out.println("\tSession time: " + sessionTime.toString()); } + + totalTime.add(sessionTime); + lmsCore.setTotalTime(totalTime.toString()); + + if(_Debug) + { System.out.println("\t\tTotal time: " + totalTime.toString()); } + + // If changes are left uncommitted when LMSFinish + // is called, the LMS forces an LMSCommit. + if ( lmsCore.getExit().getValue().equalsIgnoreCase("suspend") ) + { lmsCore.setEntry("resume"); } else { lmsCore.setEntry(""); } + + if ( lmsCore.getLessonStatus().getValue().equalsIgnoreCase("not attempted") ) + { lmsCore.setLessonStatus("incomplete"); } + + this.theSCOData.setCore(lmsCore); + + this.arewefinishing=true; + System.out.println("About calling LMSCommit from within LMSFinish with finalizing modifier\n"); + result = LMSCommit(""); + this.arewefinishing=false; + + if ( result != cmiBooleanTrue ) + { //no need to set result since we inherit a false + if ( _Debug ) { System.out.println("LMSCommit failed causing LMSFinish to fail."); } + } + else + { + isLMSInitialized = false; + result = cmiBooleanTrue; // successful completion + } + } + } + else + { + this.lmsErrorManager.SetCurrentErrorCode("201"); + } + + if ( _Debug ) + { + System.out.println(""); + System.out.println("***************************"); + System.out.println("Done Processing LMSFinish()"); + System.out.println("***************************"); + System.out.println(" returning "+result); + // tfield.setText("----FINISH Has been processed !"); + } + if (result==cmiBooleanTrue) { + //Uninitializing applet after finish + this.isLMSInitialized = false; + } + return result; + } + + + public String KeepAlive() + { + if ( _Debug ) + { + System.out.println("*****************"); + System.out.println("In API::KeepAlive"); + System.out.println("*****************"); + } + String result = cmiBooleanFalse; // assume failure + ServletProxy servletProxy = new ServletProxy( this.servletURL, this.cookie); + String calltoserver = servletProxy.KeepAlive(); + + if (calltoserver.startsWith("OK")) { + result=cmiBooleanTrue; + } else { + LastServerError=calltoserver; + } + + if ( _Debug ) + { + System.out.println("***************************"); + System.out.println("Done Processing KeepAlive()"); + System.out.println("***************************"); + System.out.println("RESULT is:"+result); + } + return result; + } + + + /*************************************************************************** + ** + ** Method: LMSGetValue(String element) + ** Input: String element + ** Output: String value of the cmi datamodel element named "element". + ** + ** Description: + ** Returns the current value of the cmi datamodel element named "element". + ** + ***************************************************************************/ + public String LMSGetValue(String element) + { + if ( _Debug ) + { + System.out.println("*******************"); + System.out.println("In API::LMSGetValue"); + System.out.println("*******************"); + System.out.println(""); + } + + if ( CheckInitialization() != true ) + { + //LMS is not initialized + if(_Debug) + { + System.out.println("LMS Not Initialized"); + } + String emptyString = new String(""); + return emptyString; + } + + if(_Debug) + { + System.out.println("Request being processed: LMSGetValue(" + element + ")"); + } + + CMIRequest request = new CMIRequest(element,true); + + if ( _Debug ) + { + System.out.println("Looking for the element " + request.getRequest() ); + } + + this.lmsErrorManager.ClearCurrentErrorCode(); + this.dmErrorManager.ClearCurrentErrorCode(); + String rtnVal = null; + + DataModelInterface dmInterface = new DataModelInterface(); + rtnVal = dmInterface.processGet(element,theSCOData,dmErrorManager); + + // Set the LMS Error Manager from the DataModel Manager + lmsErrorManager.SetCurrentErrorCode(dmErrorManager.GetCurrentErrorCode()); + + if ( rtnVal != null ) + { + if ( _Debug ) + { + System.out.println("LMSGetValue() found!"); + System.out.println("Returning: "+ rtnVal); + } + } + else + { + if ( _Debug ) + { + System.out.println("Found the element, but the value was null"); + } + rtnVal = new String(""); + } + + if ( _Debug ) + { + System.out.println(""); + System.out.println("************************************"); + System.out.println("Processing done for API::LMSGetValue"); + System.out.println("************************************"); + System.out.println(" returning "+rtnVal); + } + return rtnVal; + } + + + /*************************************************************************** + ** + ** Method: LMSSetValue(String element, String value) + ** Input: String element - cmi data model element (e.g. cmi.core.student_id + ** String value - value to apply to the data element + ** Output: none + ** + ** Description: + ** Sets the cmi datamodel element to the specified value + ** + ***************************************************************************/ + public String LMSSetValue(String element, String value) + { + String result = cmiBooleanFalse; + + if ( _Debug ) + { + System.out.println("*******************"); + System.out.println("In API::LMSSetValue"); + System.out.println("*******************"); + System.out.println(""); + } + + this.lmsErrorManager.ClearCurrentErrorCode(); + this.dmErrorManager.ClearCurrentErrorCode(); + + if ( CheckInitialization() != true ) + { + //LMS is not initialized + System.out.println("**********************************************************************"); + System.out.println("In API::LMSSetValue ---> LMS IS NOT INITIALIZED ---> NOT SETTING VALUE"); + System.out.println("**********************************************************************"); + System.out.println("The request was: LMSSetValue (element="+element+", value="+value); + return result; + } + + String setValue; + + // Check for "null" is a workaround described in "Known Problems" + // in the header. + String tempValue = String.valueOf(value); + if ( tempValue.equals("null") ) + { + setValue = new String(""); + } + else + { + setValue = tempValue; + } + + + String theRequest = element + "," + setValue; + if(_Debug) + { + System.out.println("Request being processed: LMSSetValue(" + theRequest + ")"); + System.out.println( "Looking for the element " + element ); + } + + DataModelInterface dmInterface = new DataModelInterface(); + dmInterface.processSet(theRequest,theSCOData,dmErrorManager); + + // Set the LMS Error Manager from the DataModel Manager + lmsErrorManager.SetCurrentErrorCode(dmErrorManager.GetCurrentErrorCode()); + if ( lmsErrorManager.GetCurrentErrorCode() == "0" ) + { + result = cmiBooleanTrue; // success + } + + if ( _Debug ) + { + System.out.println(""); + System.out.println("************************************"); + System.out.println("Processing done for API::LMSSetValue"); + System.out.println("************************************"); + System.out.println(" returning "+result); + } + return result; + } + + /*************************************************************************** + ** + ** Method: LMSCommit() + ** Input: none + ** Output: none + ** + ** Description: + ** Applies the SCO data model elements set using LMSSetValue + ** to LMS data model elements and saves them (on the server). + ** + ***************************************************************************/ + public String LMSCommit(String param) + { + if ( _Debug ) + { + System.out.println("*************************"); + System.out.println("Processing API::LMSCommit"); + System.out.println("*************************"); +// tfield.setText("during COMMIT to server"); + } + + String result = cmiBooleanFalse; // assume failure + // Make sure param is empty string "" - as per the API spec + // Check for "null" is a workaround described in "Known Problems" + // in the header. + String tempParm = String.valueOf(param); + if ( (tempParm.equals("null") || tempParm.equals("")) == true ) + { + if ( CheckInitialization() != true ) + { //LMS is not initialized + LastServerError="LMSFinish without LMSInitialize"; + return result; } + if ( _Debug ) + { System.out.println("The SCO Data Manager for the current SCO contains The following:"); + theSCOData.getCore().showData(); } + + ServletProxy servletProxy = new ServletProxy( this.servletURL, this.cookie); + String servletResult = servletProxy.PutSCOData(this.theSCOData); + if ( servletResult.equals("OK") != true ) + { + this.lmsErrorManager.SetCurrentErrorCode("101"); + if ( _Debug ) + { + System.out.println("Put to Server was NOT successful!"); + } + //since failure is assumed, no need to set result + LastServerError=servletResult; + } + else + { + this.lmsErrorManager.ClearCurrentErrorCode(); + result = cmiBooleanTrue; // successful completion + if ( _Debug ) + { + System.out.println("Put to Server succeeded!"); + } + } + } + else + { + this.lmsErrorManager.SetCurrentErrorCode("201"); + } + + if ( _Debug ) + { +// tfield.setText("----LMSCommit LMSCommit LMSCommit"); + System.out.println(""); + System.out.println("**********************************"); + System.out.println("Processing done for API::LMSCommit"); + System.out.println("**********************************"); + System.out.println(" returning "+result); +// tfield.setText("----COMMITTED OK"); + } + return result; + } + + /*************************************************************************** + ** + ** Method: LMSGetLastError() + ** Input: none + ** Output: String - error code set by the last API function + ** + ** Description: + ** Retrieves the error code set by the most recently executed API function + ** (Note: Each API function sets or clears the error code.) + ** + ***************************************************************************/ + //public class LMSGetLastError{ + public String LMSGetLastError() + { + if ( _Debug ) + { + System.out.println("In API::LMSGetLastError()"); + } + return APIAdapterApplet.lmsErrorManager.GetCurrentErrorCode(); + } + //public static String LMSGetLastError="1"; + // public String LMSGetLastError = "InsideImplemented"; + // } + + /*************************************************************************** + ** + ** Method: LMSGetErrorString( String errorCode) + ** Input: String errorCode - the error code to lookup + ** Output: String - the text associated with the errorCode + ** + ** Description: + ** This function returns the text associated with an error code + ** + ***************************************************************************/ + public String LMSGetErrorString( String errorCode) + { + if ( _Debug ) + { + System.out.println("In API::LMSGetErrorString()"); + } + return this.lmsErrorManager.GetErrorDescription(errorCode); + } + + /*************************************************************************** + ** + ** Method: LMSGetDiagnostic( String errorCode) + ** Input: String errorCode - the error code to lookup + ** Output: String - the vendor specific diagnostic text associated with the + ** errorCode + ** + ** Description: + ** This function returns the vendor specific diagnostic text associated + ** with an error code + ** + ***************************************************************************/ + public String LMSGetDiagnostic( String errorCode) + { + if ( _Debug ) + { + System.out.println("In API::LMSGetDiagnostic()"); + } + return this.lmsErrorManager.GetErrorDiagnostic(errorCode); + } + +} Index: openacs-4/packages/lorsm/src/java/org/adl/samplerte/client/LMSErrorManager.java =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/src/java/org/adl/samplerte/client/LMSErrorManager.java,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/src/java/org/adl/samplerte/client/LMSErrorManager.java 13 Aug 2007 09:20:15 -0000 1.2 @@ -0,0 +1,231 @@ +/******************************************************************************* +** +** Filename: LMSErrorManager.java +** +** File Description: +** +** This class implements the error handling capabilities of the RTE API. It +** manages the error codes set by the API functions in the API Adapter Applet. +** For purposes of this example, this class uses a hardcoded array to store +** the error mapping. +** +** Author: ADL Technical Team +** +** Contract Number: +** Company Name: CTC +** +** Module/Package Name: org.adl.lms.client +** Module/Package Description: Client side Sample RTE classes +** +** Design Issues: +** +** Implementation Issues: +** Known Problems: +** Side Effects: +** +** References: ADL SCORM +** +/******************************************************************************* +** +** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non- +** exclusive, royalty free, license to use, modify and redistribute this +** software in source and binary code form, provided that i) this copyright +** notice and license appear on all copies of the software; and ii) Licensee +** does not utilize the software in a manner which is disparaging to CTC. +** +** This software is provided "AS IS," without a warranty of any kind. ALL +** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON- +** INFRINGEMENT, ARE HEREBY EXCLUDED. CTC AND ITS LICENSORS SHALL NOT BE LIABLE +** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL CTC OR ITS +** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, +** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER +** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF +** OR INABILITY TO USE SOFTWARE, EVEN IF CTC HAS BEEN ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGES. +** +*******************************************************************************/ + +package org.adl.samplerte.client; + +import java.lang.*; + +public class LMSErrorManager +{ + + private static String currentErrorCode; + + private static String[][] errors = + { + {"0", "No Error", + "The previous LMS API Function call completed successfully."}, + {"101", "General Exception", + "An unspecified, unexpected exception has occured"}, + {"201", "Invalid argument error", ""}, + {"202", "Element cannot have children", ""}, + {"203", "Element not an array - cannot have count", ""}, + {"301", "Not initialized", "The LMS is not initialized."}, + {"401", "Not implemented error", + "The data model element in question was not implemented"}, + {"402", "Invalid set value, element is a keyword", + "Trying to set a reserved keyword in the data model" + + "Trying to set a keyword (_count, _children, or _version) " + + "This is prohibited"}, + {"403", "Element is read only", + "Data Element is Read Only (Not Writeable)"+ + "Cannot call LMSSetValue() for the element in question"}, + {"404", "Element is write only", + "Data Element is Write Only (Not Readable)"+ + "Cannot call LMSGetValue() for the element in question"}, + {"405", "Incorrect Data Type", + "Invalid Type being used for setting element"+ + "The type being used as the set value argument does not match" + + " that of the element being set"} + }; + + /**************************************************************************** + ** + ** Method: LMSErrorManager() + ** Input: none + ** Output: none + ** + ** Description: + ** Default Constructor - intializes the current error code to "No Error". + ** + ****************************************************************************/ + public void LMSErrorManager() + { + currentErrorCode = "0"; + } + + + /**************************************************************************** + ** + ** Method: GetCurrentErrorCode() + ** Input: none + ** Output: String - current error code + ** + ** Description: + ** Returns the value of the Current Error Code that was set by the most + ** recent API call. + ** + ****************************************************************************/ + public String GetCurrentErrorCode() + { + return currentErrorCode; + } + + /**************************************************************************** + ** + ** Method: SetCurrentErrorCode(String code) + ** Input: String code - The error code (from the predefined list of codes) + ** Output: none + ** + ** Description: + ** Sets the value of the Current Error Code. + ** + ****************************************************************************/ + public void SetCurrentErrorCode(String code) + { + + if((code != null) && (code != "")) + { + this.currentErrorCode = code; + } + else + { + this.currentErrorCode = "0"; + } + + + } + + /**************************************************************************** + ** + ** Method: ClearCurrentErrorCode() + ** Input: none + ** Output: none + ** + ** Description: + ** Sets the value of the Current Error Code to "No Error". + ** + ****************************************************************************/ + public void ClearCurrentErrorCode() + { + this.currentErrorCode = errors[0][0]; + } + + + /**************************************************************************** + ** + ** Method: GetErrorDescription(String code) + ** Input: String code - error code + ** Output: String - the description associated with the given error code + ** + ** Description: + ** Retrieves and returns the text associated with the given error code + ** + ****************************************************************************/ + public String GetErrorDescription(String code) + { + if((code != null) && (code != "")) + { + // retrieves and returns the description of the provided error code + return GetErrorElement(code)[1]; + } + else + { + return ""; + } + } + + /**************************************************************************** + ** + ** Method: GetErrorDiagnostic(String code) + ** Input: String code - error code + ** Output: String - the diagnostic text associated with the given error code + ** + ** Description: + ** Retrieves and returns the diagnostic text associated with the error code + ** + *****************************************************************************/ + public String GetErrorDiagnostic( String code) + { + if((code != null) && (code != "")) + { + // retrieves and returns the diagnostic text of the provided error code + return GetErrorElement(code)[2]; + } + else + { + // returns diagnostic text of previous error + return GetErrorElement(currentErrorCode)[2]; + } + } + + /**************************************************************************** + ** + ** Method: GetErrorElement(String code) + ** Input: String code - error code + ** Output: String[] - the array corresponding to the element identified by + ** the given error code + ** + ** Description: + ** Private function that gets the array containing the error element info + ** identified by the given error code + ** + ****************************************************************************/ + private String[] GetErrorElement(String code) + { + for(int i=0; i 0 } { + ns_log debug "SCORM parents: Found parent: $father which is $father_type " + #the following query should include "self" where self is current ims_item_id + + if { [ string equal $father_type "ims_manifest_object" ] } { + #since we have a manifest i will check all orgs below. + if { [ db_0or1row hasmanincompletedchildren { + select * from ( + select + o.man_id, org_title as item_title, org_id as item_id + from + ims_cp_organizations o, ims_cp_manifest_class im + where + o.man_id=:currentcourse + and im.man_id=o.man_id + and im.community_id=:community_id) as allitems where item_id + not in + ( select cmi.item_id from lorsm_cmi_core cmi, lorsm_student_track track + where + cmi.man_id=:currentcourse + and + track.user_id=:user_id + and + cmi.track_id=track.track_id + and + track.community_id=:community_id + and + lesson_status in + ( 'completed', 'passed' )) + limit 1 } ] } { + ns_log debug "SCORM parents: at least one incomplete sub-org ($item_id)" + set target_status "incomplete" + set target_comment "MAN TRACKING" + } else { + ns_log debug "SCORM parents: no incompleted sub-orgs" + set target_status "completed" + set target_comment "MAN TRACKING" + } + } else { + if { [ db_0or1row hasblockincompletedchildren { + select * from ( + select + o.man_id, item_title, ims_item_id as item_id + from + ims_cp_items i, ims_cp_organizations o, ims_cp_manifest_class im + where + i.org_id=o.org_id + and im.man_id=o.man_id + and o.man_id= :currentcourse + and im.community_id= :community_id + and i.parent_item= :father + ) as allitems where item_id + not in + ( select cmi.item_id from lorsm_cmi_core cmi, lorsm_student_track track + where + cmi.man_id=:currentcourse + and + track.user_id=:user_id + and + cmi.track_id=track.track_id + and + track.community_id=:community_id + and + lesson_status in + ( 'completed', 'passed' )) + limit 1 } ] } { + ns_log debug "BLOCK: at least 1 incomplete children (see $item_id)" + set target_status "incomplete" + set target_comment "BLOCK TRACKING" + } else { + ns_log debug "BLOCK: no incomplete or unvisited children" + set target_status "completed" + set target_comment "BLOCK TRACKING" + } + } + + ns_log debug "SCORM Parents: We are going to (check) set: $target_status on $father " + + if { [ db_0or1row isanysuspendedsession " + select lorsm.track_id as block_track_id, lesson_status as lesson_status_old + from lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $currentcourse + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $currentcourse + and + cmi.item_id = $father + order by + lorsm.track_id desc limit 1 " ] } { + if { ! [ string equal lesson_status_old target_status ] } { + #UPDATE + set todo "UPDATE lorsm_cmi_core SET lesson_status = '$target_status' " + append todo " WHERE track_id=$block_track_id" + db_dml todo $todo + if { [db_resultrows] == 1 } { + ns_log debug "SCORM: lesson_status processing UPDATE: '$todo' successfull" + #POST PROCESSING + if { ! [string equal $father_type "ims_manifest_object" ] } { + ns_log debug "SCORM parents: calling self" + lorsm::delivery::scorm::check_parents -ims_item_id $father + ns_log debug "SCORM parents: end calling self" + } + + } else { + ns_log warning "SCORM parents: lesson_status processing UPDATE: '$todo' not successfull -> please check" + } + + } else { + ns_log debug "SCORM Parents: not updating, upper status already set" + } + } else { + #fresh tracking record + set block_track_id [lorsm::track::new \ + -user_id $user_id \ + -community_id $community_id \ + -course_id $currentcourse] + #INSERT NEW TRACK FOR ITEM + db_dml lmsinitialize { insert into lorsm_cmi_core(track_id,man_id,item_id,student_id,student_name, + lesson_location, + lesson_status, + launch_data, + comments,comments_from_lms, session_time, total_time, time_stamp) + values(:block_track_id,:currentcourse,:father,:username,:name, + :currentcourse, + :target_status, + '', + '',:target_comment,0,0,CURRENT_TIMESTAMP) } + if { [db_resultrows] == 1 } { + ns_log debug "SCORM: lesson_status processing INSERT: $block_track_id to $target_status successfull" + #POST PROCESSING + if { ! [string equal $father_type "ims_manifest_object" ] } { + ns_log debug "SCORM parents: calling self" + lorsm::delivery::scorm::check_parents -ims_item_id $father + ns_log debug "SCORM parents: end calling self" + } + } else { + ns_log warning "SCORM parents: lesson_status processing INSERT: '$block_track_id' to $target_status not successfull -> please check" + } + + } + + } else { + ns_log Warning "SCORM parents: no father found" + } + #} + return 0 + } + +} Index: openacs-4/packages/lorsm/tcl/lorsm-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/tcl/lorsm-procs.tcl,v diff -u -N -r1.16 -r1.17 --- openacs-4/packages/lorsm/tcl/lorsm-procs.tcl 6 Apr 2007 19:30:20 -0000 1.16 +++ openacs-4/packages/lorsm/tcl/lorsm-procs.tcl 13 Aug 2007 09:20:15 -0000 1.17 @@ -622,13 +622,13 @@ # that could be expensive if the tree is long or deep. array set visited_items [list] while { $count < $items_count } { - ns_log notice "loop [incr i]" + ns_log debug "lorsm::get_items_indent loop [incr i]" if {$i > 2} {break} foreach item $items_list { set item_id [lindex $item 0] - ns_log notice "item_id $item_id [info exists visited_items($item_id)]" + ns_log debug "lorsm::get_items_indent item_id $item_id [info exists visited_items($item_id)]" if {![info exists visited_items($item_id)]} { - ns_log notice "adding to array item_id $item_id" + ns_log debug "lorsm::get_items_indent adding to array item_id $item_id" set visited_items($item_id) $item_id set indent [expr [lindex $item 1] + 1] foreach ims_item_id [db_list get_items "select ims_item_id from ims_cp_items where parent_item = :item_id and org_id = :org_id $exclude_where"] { Index: openacs-4/packages/lorsm/templates/lorsm-default.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/templates/lorsm-default.adp,v diff -u -N -r1.5 -r1.6 --- openacs-4/packages/lorsm/templates/lorsm-default.adp 22 Dec 2006 18:16:10 -0000 1.5 +++ openacs-4/packages/lorsm/templates/lorsm-default.adp 13 Aug 2007 09:20:16 -0000 1.6 @@ -19,7 +19,7 @@ - image + image Index: openacs-4/packages/lorsm/templates/lorsm-default.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/templates/lorsm-default.tcl,v diff -u -N -r1.9 -r1.10 --- openacs-4/packages/lorsm/templates/lorsm-default.tcl 22 Dec 2006 18:16:10 -0000 1.9 +++ openacs-4/packages/lorsm/templates/lorsm-default.tcl 13 Aug 2007 09:20:16 -0000 1.10 @@ -14,6 +14,7 @@ # There are pages that are not necesarily part of one ims_item_id # but are part of a particular resource. + if { [info exists content(item_id)] } { set write_p [fs::item_editable_p -item_id $content(item_id)] } else { @@ -22,11 +23,18 @@ } if {![empty_string_p $imsitem_id]} { - set imsitem_id [content::item::get_live_revision -item_id $imsitem_id] + set live_imsitem_id [content::item::get_live_revision -item_id $imsitem_id] + if {![empty_string_p $live_imsitem_id]} { + set imsitem_id $live_imsitem_id + } else { + ns_log warning "no live revision for item $imsitem_id" + } # See if they have write and the object is browser editable to offer an edit link. + if { [info exists content(item_id)] } { set write_p [permission::write_permission_p -object_id $imsitem_id] - if { $write_p && [info exists content(item_id)] } { + if { $write_p } { set write_p [fs::item_editable_p -item_id $content(item_id)] + } } else { # No content to edit set write_p 0 Index: openacs-4/packages/lorsm/www/admin/course-add-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/admin/course-add-2.tcl,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/lorsm/www/admin/course-add-2.tcl 31 Dec 2006 00:36:04 -0000 1.1 +++ openacs-4/packages/lorsm/www/admin/course-add-2.tcl 13 Aug 2007 09:20:16 -0000 1.2 @@ -31,6 +31,9 @@ # Permissions set user_id [ad_conn user_id] +# checl Permissions on target folder +ad_require_permission $folder_id admin + # unzips the file if { ![empty_string_p $upload_file] && [ catch {set tmp_dir [lors::imscp::expand_file $upload_file ${upload_file.tmpfile} lors-imscp-$course_id] } errMsg] } { @@ -41,24 +44,22 @@ # if it is not blank... if {![empty_string_p $upload_file]} { ns_log Debug "LORS Package: made directory $tmp_dir to extract from ${upload_file.tmpfile} ($upload_file)\n" + #checks for nested imsmanifest.xml and sets root there + while { [llength [glob -nocomplain [file join $tmp_dir *]]] == 1 } { + set tmp_dir [lindex [glob -nocomplain [file join $tmp_dir *]] 0] set allfiles [lors::imscp::dir_walk $tmp_dir] - + } } else { set allfiles [lors::imscp::dir_walk $directory] - } - -# Permissions on target folder -ad_require_permission $folder_id admin - - +#unusefully duplicates, leaving unzips around # unzips the file -if { ![empty_string_p $upload_file] && - [ catch {set tmp_dir [lors::imscp::expand_file $upload_file ${upload_file.tmpfile} lors-imscp-$course_id] } errMsg] } { - ad_return_complaint 1 "[_ lorsm.lt_The_uploaded_file_doe]" - ad_script_abort -} +#if { ![empty_string_p $upload_file] && +# [ catch {set tmp_dir [lors::imscp::expand_file $upload_file ${upload_file.tmpfile} lors-imscp-$course_id] } errMsg] } { +# ad_return_complaint 1 "[_ lorsm.lt_The_uploaded_file_doe]" +# ad_script_abort +#} # search for manifest file set file imsmanifest.xml Index: openacs-4/packages/lorsm/www/admin/course-add-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/admin/course-add-3.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/lorsm/www/admin/course-add-3.tcl 24 Jan 2007 02:36:30 -0000 1.3 +++ openacs-4/packages/lorsm/www/admin/course-add-3.tcl 13 Aug 2007 09:20:16 -0000 1.4 @@ -90,7 +90,12 @@ # We need to separate folders (since now all are cr_items) one for the files (content) and the other # one for the created cr_items - set new_parent_id [lors::cr::add_folder -parent_id $parent_id -folder_name $cr_dir] + + if { [ catch {set new_parent_id [lors::cr::add_folder -parent_id $parent_id -folder_name $cr_dir]} errMsg] } { + ns_write "

Unfortunately the same context contains a course with same exact name. hit back and change name.

" + ad_script_abort + } + set new_items_parent_id [lors::cr::add_folder -parent_id $parent_id -folder_name "${cr_dir}_items"] # PERMISSIONS FOR FILE-STORAGE Index: openacs-4/packages/lorsm/www/admin/tracking-rte/drill-student-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/admin/tracking-rte/drill-student-2.tcl,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/lorsm/www/admin/tracking-rte/drill-student-2.tcl 31 Dec 2006 00:36:09 -0000 1.1 +++ openacs-4/packages/lorsm/www/admin/tracking-rte/drill-student-2.tcl 13 Aug 2007 09:20:16 -0000 1.2 @@ -82,13 +82,17 @@ # { title "" "no_sort" "Item: $item_id $indent [if {![empty_string_p $identifierref]} {set href \"$item_title\"} else {set href \"AAA $item_title\"}]" } # } + regsub -all {[\{\}]} $org_title "" org_title + append orgs_list "
" - append orgs_list "" + append orgs_list "" + set indent_items [lorsm::get_items_indent -org_id $org_id] + db_foreach organization_item { SELECT o.object_id, - repeat(' ', (tree_level(tree_sortkey) - :indent)* 2) as indent, + --repeat(' ', (tree_level(tree_sortkey) - :indent)* 2) as indent, i.ims_item_id, i.item_title as item_title, i.hasmetadata, @@ -101,32 +105,46 @@ FROM acs_objects o, ims_cp_items i, ims_cp_manifests m WHERE - o.object_type = 'ims_item' + o.object_type like 'ims_item_object' AND i.org_id = :org_id AND o.object_id = i.ims_item_id AND m.man_id = :man_id ORDER BY - object_id, tree_sortkey + object_id + --, tree_sortkey } { + foreach indent_item $indent_items { + set indent_item_id [lindex $indent_item 0] + set indent_indent [lindex $indent_item 1] + if { [string equal $indent_item_id $ims_item_id] } { + set indent $indent_indent + } + } + + set table_item "" + + for {set x 0} {$x<$indent} {incr x} { + append table_item "" + } + append table_item "" } + append orgs_list "
Organization: $org_title ($org_id)
$org_title (id: $org_id)
" + + if { [empty_string_p $identifierref] } { - set table_item "" } else { #set table_item "" + append orgs_list " : No RTE scorm data " append orgs_list "" } else { append orgs_list "" + append orgs_list "
Item: $item_id $indent AAA $item_title" - #set table_item "Item: $item_id $indent AAA $item_title" + append table_item "Item: $ims_item_id $indent $item_title" + #set table_item "Item: $item_id $indent AAA $item_titleItem: $item_id $indent [string trim $item_title]" - set table_item "$indent $indent [string trim $item_title]" + append table_item "[string trim $item_title], (id: $ims_item_id)" } # set table_item [concat $table_item [ad_table -Tmissing_text $missing_text -Textra_vars {fs_local_package_id track_id} -Ttable_extra_html $table_extra_html $table_def]] #set table_item [concat $table_item [ad_table -Tmissing_text $missing_text -Textra_vars {fs_local_package_id track_id} -Ttable_extra_html $table_extra_html $table_def]] append orgs_list [string trim $table_item] - - - set item_table "" db_foreach student_activity { @@ -148,7 +166,7 @@ and user_id=:user_id and - imsitems.item_id=cmi.item_id + imsitems.ims_item_id=cmi.item_id order by cmi.track_id asc } { @@ -167,17 +185,22 @@ } if { [empty_string_p $item_table] } { - append orgs_list ": No scorm data
" append orgs_list "" append orgs_list "" append orgs_list $item_table - append orgs_list "
scorestatustotal timefirst visitdetail sessions
" + append orgs_list "
" + append orgs_list "" } + +append orgs_list "" append orgs_list "" } Index: openacs-4/packages/lorsm/www/delivery/applet.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/applet.adp,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/applet.adp 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/applet.adp 13 Aug 2007 09:20:16 -0000 1.3 @@ -1,425 +1,51 @@ - -this.releasemenu=null; -this.APIFinder=null; -this.initialized=false; -this.finished=false; -this.tries=0; -this.megatries=0; -this.bored=0; -this.finishing=false; -this.withinfinish=false; -this.withininitialize=false; - -function EndingNow() { - //UNLOADING APPLET - //alert("APPLET UNLOADING"); - //this.parent.location.href="blank.html"; - //this.parent.location.replace("blank.html"); - //this.parent.location.reload(true); - self.document.location.href="blank.html"; - self.document.location.replace("blank.html"); - self.document.src="blank.html"; - self.document.write("TERMINATING"); - //self.document.location.reload(true); - //APIFinder.stop(); - //APIFinder.destroy(); - parent.API=null; - APIFinder=null; - APIHolder=null; - API=null; - return(true); -} - -function KeepAlive() { - //number of seconds * 1000 - reloadtime=@ses_renew@*1000; - myTimer=setTimeout("ReLoad()",reloadtime); - debug("scheduling keepalive every "+reloadtime/1000+" seconds"); -} - -function ReLoad() { - //keepalive will always be there: no more just initialized if( ! initialized ) { debug("deactivating keepalive");return; } - debug("within reload()"); - var rnumb = Math.floor(Math.random()*999); - temp = "keepalive?Rand="+rnumb; - parent.frames['keepalive'].location.href="blank.html"; - parent.frames['keepalive'].document.location.replace("blank.html"); - parent.frames['keepalive'].document.location.reload(true); - parent.frames['keepalive'].document.location.href=temp; - parent.frames['keepalive'].document.location.replace(temp); - parent.frames['keepalive'].document.location.reload(true); - parent.frames['keepalive'].document.src ="keepalive?Rand="+rnumb; - isalive=APIFinder.KeepAlive(); - if(!(isalive=='true')) { - - message="Server failure: Error in communication to server:
"+APIFinder.LastServerError; - parent.frames['menu'].writit(message,'usermessage'); -
- - debug("server error in keepalive"); - - APIFinder.LastServerError=""; - } else { - - message="Server online"; - parent.frames['menu'].writit(message,'usermessage'); - - - debug("server OK in keepalive"); - - } - KeepAlive(); -} - - -function APIHolder() { - //this is just a placeholder -} - -function LMSInitialize(placeholder) { - debug("sco called LMSInitialize ("+placeholder+")"); - initialized=APIFinder.LMSInitialize(placeholder); - debug("returning from LMSInitialize =("+initialized+")"); - if(initialized=='true') { - - parent.frames['menu'].toggleBox('menudiv',0); - parent.frames['menu'].writit('Course initialized.
The menu returns when you exit the module.

','usermessage'); - parent.frames['menu'].writit('Abort Course
(clicking this will not record tracking information)
','abort'); -
- APIFinder.LastServerError=""; - } else { - - message="LMSInitialize: Error in communication to server:
"+APIFinder.LastServerError+""; - parent.frames['menu'].writit(message,'usermessage'); -
- - debug("server error in LMSInitialize"); - - } - return initialized; -} - -function BackToBody() { - try { - debug("doing backtobody"); - - parent.frames['menu'].writit('','abort'); - parent.frames['menu'].writit('','usermessage'); - - messaging("Unloading course"); - parent.frames['content'].document.location.href = "body?man_id=@man_id@"; - } catch (err) { - debug("FAILURE calling backtobody FAILED"); - } - debug("ending backtobody"); - finishing=false; -} - -function LMSFinish(placeholder) { - if(!(initialized=='true')) { - debug("SCO called LMSFinish when NOT INITIALIZED!"); - } - finishing=true; - - parent.frames['menu'].writit('Sending tracking to server....','usermessage'); - - debug("sco called LMSFinish("+placeholder+")"); - debug("calling LMSfinish =("+finished+")"); - finished=APIFinder.LMSFinish(placeholder); - debug("returning from LMSfinish =("+finished+")"); - //now we schedule a page unload AFTER the course has received the LMSFINISH ok - if(finished=='true') { - //we set initialized to false ONLY when finished has been processed - //it could be some courses try finish more than once following an error - initialized=false; - myTimer=setTimeout("BackToBody()",1000) - APIFinder.LastserverError=""; - - parent.frames['menu'].writit('','abort'); - parent.frames['menu'].toggleBox('menudiv',1); - parent.frames['menu'].writit('Tracking is OK','usermessage'); - - } else { - //Some error occourred. not clear at this stage if SERVER SIDE or what - finishing=false; - - //better be conservative. don't give'em menu back - //parent.frames['menu'].writit('','abort'); - //parent.frames['menu'].toggleBox('menudiv',1); - message="LMSFinish: Error in communication to server:
"+APIFinder.LastServerError+""; - parent.frames['menu'].writit(message,'usermessage'); -
- - debug("ERROR during LMSFinish CALL !!!"); - - } - return finished; -} - -function LMSGetValue(name) { - debug("sco called LMSGetValue("+name+")"); - getvalue=APIFinder.LMSGetValue(name); - debug("LMSGetValue("+name+") returns ("+getvalue+")"); - return(getvalue); -} - -function LMSCommit(placeholder) { - debug("sco called LMSCommit("+placeholder+")"); - committed=APIFinder.LMSCommit(placeholder); - if(!(committed=='true')) { - - message="Commit: Error in communication to server:
"+APIFinder.LastServerError+""; - parent.frames['menu'].writit(message,'usermessage'); -
- - debug("ERROR during LMSCommit CALL !!!"); - - } else { - - parent.frames['menu'].writit('Committed OK','usermessage'); - - APIFinder.LastServerError=""; - } - return committed; -} - -function LMSSetValue(name,value) { - debug("sco called LMSSetValue("+name+","+value+")"); - setvalue=APIFinder.LMSSetValue(name,value); - debug("LMSsetvalue returning "+setvalue+" "); - return (setvalue); -} - -function LMSGetLastError() {debug ("sco called LMSGetLastError ("+")"); return APIFinder.LMSGetLastError()} -function LMSGetErrorString(number) {debug ("sco called LMSGetErrorString ("+number+")"); return APIFinder.LMSGetErrorString(number)} -function LMSGetDiagnostic(placeholder) {debug ("sco called LMSGetDiagnostic ("+placeholder+")"); return APIFinder.LMSGetDiagnostic(placeholder)} - - -APIHolder.prototype.LMSInitialize=LMSInitialize; -APIHolder.prototype.LMSFinish=LMSFinish; -APIHolder.prototype.LMSGetValue=LMSGetValue; -APIHolder.prototype.LMSCommit=LMSCommit; -APIHolder.prototype.LMSSetValue=LMSSetValue; -APIHolder.prototype.LMSGetLastError=LMSGetLastError; -APIHolder.prototype.LMSGetErrorString=LMSGetErrorString; -APIHolder.prototype.LMSGetDiagnostic=LMSGetDiagnostic; - - -function waitforapplet() { - debug("in waitforapplet"); - - if (megatries>5) { - debug("giving up"); - if(bored==0) { - bored=1; - alert("Your browser seems not to let me communicate with the applet. Please check:\n1) Java support is installed and active in the browser\n2)That your browser supports java-javascript connectivity (most versions of IE and Mozilla-compatible would be ok)\n3) If you are currentely installing Java support, please try again accesing the course after installation completion\n"); - } - this.releasemenu=-1; - return; - } - tries++; - if (tries>3) { - debug("bored with loading applet - trying something else"); - var temp=this.document.location.href; - debug(temp); - this.document.location.href="blank.html"; - this.document.location.replace("blank.html"); - this.document.location.reload(true); - this.document.location.href=temp; - this.document.location.replace(temp); - this.document.location.reload(true); - debug("waiting again"); - tries=0; megatries++; - setTimeout("waitforapplet();",1000) - } - - try { - var active=this.document.applets[0].isActive(); //mozilla error on this, IE just gives out (doesnt' go in the catch ???) - } catch (err) { - try { - var active=this.document.applets[0].isActive; //this is mozilla specific, IE is just allergic (we have enough wars not to think of browsers'.... - } catch (err2) { - debug("applet not loaded within old explorer") - debug("seems java is not installed") - } - } + - if (active) + - + + ses_renew: @ses_renew@ ses_timeout: @ses_timeout@ first_cookie: @cookie@ - - - - - - + @@ -438,32 +64,7 @@ - - - Index: openacs-4/packages/lorsm/www/delivery/applet.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/applet.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/applet.js 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,474 @@ + + +this.releasemenu=null; +this.APIFinder=null; +this.initialized=false; +this.finished=false; +this.tries=0; +this.megatries=0; +this.bored=0; +this.finishing=false; + +//this.withinfinish=false; +//this.withininitialize=false; + +function debug(message) { + if (debuglevel ==1) { + if (menu_off < 1 ) { + parent.frames['talk'].document.write(""+message+"
"); + } + } + return; + } + +function messaging(message) { + if (debuglevel ==1) { + try { + parent.frames['content'].document.write(message); + } catch (err) { + debug("Messaging error."); + } + } + return; +} + + +function BlurListener(evt) { +evt = evt || window.event; +//debug('blurlistener'); +menu_frameset=parent.document.getElementById("menuvscontent"); +menu_frameset.cols="5%,*"; +menu_frame=parent.frames['menu']; +menu_frame.toggleBox('abort',0); +menu_frame.toggleBox('btn_finish',0); +} + +function FocusListener(evt) { +evt = evt || window.event; +//debug('focuslistener'); +menu_frameset=parent.document.getElementById("menuvscontent"); +menu_frameset.cols="15%,*"; +menu_frame=parent.frames['menu']; +menu_frame.toggleBox('abort',1); +menu_frame.toggleBox('btn_finish',1); +} + +function appletending() { + // try { + // selfcheck(); + // } catch (o) { + // debug(o); + // } + self.document.location.href="blank.html"; + self.document.location.replace("blank.html"); + self.document.src="blank.html"; + self.document.write("TERMINATING"); + parent.API=null; + APIFinder=null; + APIHolder=null; + API=null; + return(true); +} + + +// function selfcheck() { + // alert(parent.window.name); + // if ( parent.window.name=='LRN_delivery_window' ) { + // parent.close(); + //alert('eeh'); + // } +// } + +function KeepAlive() { + //number of seconds * 1000 + reloadtime=this.ses_renew*1000; + myTimer=setTimeout("AliveReLoad()",reloadtime); + debug("scheduling keepalive every "+reloadtime/1000+" seconds"); +} + +function AliveReLoad() { + //keepalive will always be there: no more just initialized if( ! initialized ) { debug("deactivating keepalive");return; } + debug("within AliveReload()"); + var rnumb = Math.floor(Math.random()*999); + temp = "keepalive?Rand="+rnumb; + parent.frames['keepalive'].location.href="blank.html"; + parent.frames['keepalive'].document.location.replace("blank.html"); + parent.frames['keepalive'].document.location.reload(true); + parent.frames['keepalive'].document.location.href=temp; + parent.frames['keepalive'].document.location.replace(temp); + parent.frames['keepalive'].document.location.reload(true); + parent.frames['keepalive'].document.src ="keepalive?Rand="+rnumb; + isalive=APIFinder.KeepAlive(); + if(!(isalive=='true')) { + if (menu_off < 1 ) { + message="Server failure: Error in communication to server:
"+APIFinder.LastServerError; + parent.frames['menu'].writit(message,'usermessage'); + } else { + debug("server error in keepalive"); + } + APIFinder.LastServerError=""; + } else { + if (menu_off < 1 ) { + message="Server online"; + parent.frames['menu'].writit(message,'usermessage'); + } else { + debug("server OK in keepalive"); + } + } + KeepAlive(); +} + +function BackToBody() { + try { + debug("doing backtobody"); + if (menu_off < 1 ) { + parent.frames['menu'].writit('','abort'); + parent.frames['menu'].writit('','usermessage'); + } + messaging("Unloading course"); + if (menu_off < 1) { + parent.frames['content'].document.location.href = main_body_url; + } else { + top.document.location.href = return_url; + } + } catch (err) { + debug("FAILURE calling backtobody FAILED"); + } + debug("ending backtobody"); + finishing=false; +} + +function waitforapplet() { + debug("in waitforapplet"); + + if (megatries>5) { + debug("giving up"); + if(bored==0) { + bored=1; + alert("Your browser seems not to let me communicate with the applet. Please check:\n1) Java support is installed and active in the browser\n2)That your browser supports java-javascript connectivity (most versions of IE and Mozilla-compatible would be ok)\n3) If you are currentely installing Java support, please try again accesing the course after installation completion\n"); + } + this.releasemenu=-1; + return; + } + tries++; + if (tries>3) { + debug("bored with loading applet - trying something else"); + var temp=this.document.location.href; + debug(temp); + this.document.location.href="blank.html"; + this.document.location.replace("blank.html"); + this.document.location.reload(true); + this.document.location.href=temp; + this.document.location.replace(temp); + this.document.location.reload(true); + debug("waiting again"); + tries=0; megatries++; + setTimeout("waitforapplet();",1000) + } + + try { + var active=this.document.applets[0].isActive(); //mozilla error on this, IE just gives out (doesnt' go in the catch ???) + } catch (err) { + try { + var active=this.document.applets[0].isActive; //this is mozilla specific, IE is just allergic (we have enough wars not to think of browsers'.... + } catch (err2) { + debug("applet not loaded within old explorer") + debug("seems java is not installed") + } + } + + if (active) + { + debug("applet detected to be active"); + init(); + } + else { + debug("applet results not active right now"); + setTimeout("waitforapplet();",1000) + } +} + + +function init() { + debug("inizio toplevel findapi"); + messaging("Checking system configuration"); + var findapplets =0 ; + var numtest = 0; + //frames['menu'].document.write("this is me"); + while ( findapplets != 1 && findapplets !=2 ) { //we use this weird setting not to have to set for typeof or undefined checking + findapplets=this.document.applets.length; + debug(findapplets); + numtest++; + if (numtest>70) { + debug("i cannot see the applet loading... is java enabled and installed ?"); + messaging("Java JRE not found (error 206). Please check requirements."); + return(0); + } + } + var findAPITries = 0; + while (APIFinder == null) { + debug("whithin APIFinder while loop"); + findAPITries++; + APIFinder = this.document.applets[0]; // this returns object for opera and seems to be working + // APIFinder = this.document.applets[1]; // this returns object for opera + // APIFinder = this.document.applets['APIAdapter']; // this returns function for opera + if (findAPITries > 70) { + debug("FRAMESET Couldn't find the APIAdapter "); + messaging("Java JRE not found (error 223). Please check requirements."); + this.releasemenu=-1; + break; + } + } + if (findAPITries <=70) { + debug("Frameset FOUND API within applet (menu) - using APIfinder - loading learning object"); + this.releasemenu=1; + messaging("System check passed"); + //temporarly added for testing ADL conformance tests - which rely on typeof - miserably failing + //alert(typeof(APIFinder.LMSInitialize)); + API=new APIHolder(); + //exporting API to parent + parent.API=this.API; + //alert(typeof(API)); + debug("the type of API.LMSInitialize is "+typeof(API.LMSInitialize)); + } else { + debug("API not found, don't know what to do"); + } + //here we had a menu off switch + if (refreshFrame()==0) { + debug ("i would do reload now-- if for anything"); + messaging("Double checking system configuration."); + //alert("reload1"); + self.location.reload(); + } + //here the menu off switch would end +} + +//function closecontents() { +//alert("content going") +//parent.frames['content'].window.location.href = "blank.html"; +//if (parent.frames['content'].window.location.href != "blank.htm") { +// setTimeout("closecontents();",1000) +// } +//return(0); +//} + +function refreshFrame() { +//chiamata quando trovato adapter +//SUPERFLUO ?? +if (menu_off < 1 ) { + parent.frames['content'].window.location.href = "blank.html"; + parent.frames['content'].window.location.href = content_url; +} +//not ready yet to show menu +parent.frames['menu'].window.location.href = "blank.html"; +var gotit=null; +var findgetAppletInfo = 0; + while(gotit == null) { + debug("tipo di API (via APIfinder):"+typeof(APIFinder)); + findgetAppletInfo++; + try { + gotit=APIFinder.getAppletInfo(); + debug("we have established communication from javascript to java:"); + debug(gotit); + } + catch (err) { + debug("Your browser told me the applet was ready but now denies access to its functions, claiming \n"+err+"\n I must force reload, this way you won't see this message again, luckily.\n"); + return(0); + } + debug("activating keepalive"); + //NONO KeepAlive(); + if (menu_off < 1 ) { + parent.frames['content'].document.location.href = "blank.html"; + parent.frames['content'].document.location.href = content_url; + //let's show menu now + parent.frames['menu'].window.location.href = menu_url; + //obviously no menu if menu is off... + } else { + messaging("Please wait. Loading contents.
Attendere prego. Caricamento contenuti.
"); + parent.frames['content'].location.href = record_view_url; + } + if (findgetAppletInfo> 7) { + debug("I cannot talk to APIAdapter: try reloading me. Please notify support of your sw configuration ;) "); + return(0); + } + } + return(1); +} + + + +function APIHolder() { + //this is just a placeholder +} + +function LMSInitialize(placeholder) { + debug("sco called LMSInitialize ("+placeholder+")"); + initialized=APIFinder.LMSInitialize(placeholder); + debug("returning from LMSInitialize =("+initialized+")"); + initialized=initialized+''; + if(initialized=='true') { + if (menu_off < 1 ) { + menu_frame=parent.frames['menu']; + menu_frameset=parent.document.getElementById("menuvscontent"); + + menu_x=parent.document.getElementById("left"); + menu_x.onmouseover = FocusListener; + menu_x.onmouseout = BlurListener; + + menu_frame.toggleBox('menudiv',0); + menu_frame.toggleBox('abort',0); + menu_frame.toggleBox('btn_finish',0); + + menu_frameset.cols="5%,*"; + menu_frame.writit('EXIT
','usermessage'); + menu_frame.writit('Abort Course
(clicking this will not record tracking information)
','abort'); + menu_frame.writit('Close Unit
(force LMSFinish)
','btn_finish'); + } + APIFinder.LastServerError=""; + } else { + if (menu_off < 1 ) { + message="LMSInitialize: Error in communication to server:
"+APIFinder.LastServerError+""; + parent.frames['menu'].writit(message,'usermessage'); + } else { + debug("server error in LMSInitialize"); + } + } + return initialized+''; +} + +function LMSFinish(placeholder) { + if (menu_off < 1 ) { + menu_frame=parent.frames['menu']; + + menu_x=parent.document.getElementById("left"); + menu_x.onmouseover = ''; + menu_x.onmouseout = ''; + + menu_frameset=parent.document.getElementById("menuvscontent"); + menu_frameset.cols="40%,*"; + //stupid reload trick + //this reloads menu, showing us the beauty of realtime lesson_status changes + //but screws up applet init ? + tempvar=parent.frames['menu'].location.href; + dummyDate = new Date() ; + dummyParameter = "&" + dummyDate.getTime() + parent.frames['menu'].location.href = tempvar + dummyParameter + } + if(!(initialized=='true')) { + debug("SCO called LMSFinish ("+placeholder+") but course not initialized"); + return false; + } + finishing=true; + if (menu_off < 1 ) { + parent.frames['menu'].writit('Sending tracking to server....','usermessage'); + } + debug("APPLET.JS sco called LMSFinish("+placeholder+")"); + debug("calling LMSfinish =(\'\')"); + // Make sure param is empty string "" - as per the API spec + finished=APIFinder.LMSFinish(''); + finished=finished+''; + debug("returning from LMSfinish =("+finished+")"); + //now we schedule a page unload AFTER the course has received the LMSFINISH ok + if(finished=='true') { + //we set initialized to false ONLY when finished has been processed + //it could be some courses try finish more than once following an error + initialized=false; + debug('Within finish, before backtobody timeout'); + myTimer=setTimeout("BackToBody()",1000) + debug('Within finish, past backtobody timeout setting'); + APIFinder.LastServerError=""; + if (menu_off < 1 ) { + try { + + parent.frames['menu'].writit('','abort'); + parent.frames['menu'].writit('','btn_finish'); + parent.frames['menu'].toggleBox('menudiv',1); + parent.frames['menu'].writit('Tracking is OK','usermessage'); + } catch (err) { + debug ("cannot restore menu... what's up ?") + } + } + } else { + //Some error occourred. not clear at this stage if SERVER SIDE or what + finishing=false; + if (menu_off < 1 ) { + //better be conservative. don't give'em menu back + //parent.frames['menu'].writit('','abort'); + //parent.frames['menu'].toggleBox('menudiv',1); + message="LMSFinish: Error in communication to server:
"+APIFinder.LastServerError+""; + parent.frames['menu'].writit(message,'usermessage'); + } else { + debug("ERROR during LMSFinish CALL !!!"); + } + } + return finished; +} + +function LMSGetValue(name) { + if(!(initialized=='true')) { + debug("LMSGetValue: damn SCO called LMSGetValue("+name+") but course not initialized"); + debug("LMSGetValue: we try calling initialization ourselves"); + var temp=API.LMSInitialize(''); + debug("LMSGetValue: initialization was="+temp); + } + debug("sco called LMSGetValue("+name+")"); + getvalue=APIFinder.LMSGetValue(name); + getvalue=getvalue+''; + debug("LMSGetValue("+name+") returns ("+getvalue+")"); + return(getvalue); +} + +function LMSCommit(placeholder) { + if(!(initialized=='true')) { + debug("LMSCommit: damn SCO called LMSGetValue("+name+") but course not initialized"); + debug("LMSCommit: we try calling initialization ourselves"); + var temp=API.LMSInitialize(''); + debug("LMSCommit: initialization was="+temp); + } + debug("sco called LMSCommit("+placeholder+")"); + committed=APIFinder.LMSCommit(placeholder); + committed=committed+''; + if(!(committed=='true')) { + if (menu_off < 1 ) { + message="Commit: Error in communication to server:
"+APIFinder.LastServerError+""; + parent.frames['menu'].writit(message,'usermessage'); + } else { + debug("ERROR during LMSCommit CALL !!!"); + } + } else { + if (menu_off < 1 ) { + parent.frames['menu'].writit('Committed OK','usermessage'); + } + APIFinder.LastServerError=""; + } + return committed; +} + +function LMSSetValue(name,value) { + if(!(initialized=='true')) { + debug("LMSSetValue: damn SCO called LMSGetValue("+name+") but course not initialized"); + debug("LMSSetValue: we try calling initialization ourselves"); + var temp=API.LMSInitialize(''); + debug("LMSSetValue: initialization was="+temp); + } + debug("sco called LMSSetValue("+name+","+value+")"); + setvalue=APIFinder.LMSSetValue(name,value); + setvalue=setvalue+''; + debug("LMSsetvalue returning "+setvalue+" "); + return (setvalue); +} + +function LMSGetLastError() {debug ("sco called LMSGetLastError ("+")"); return APIFinder.LMSGetLastError()+''} +function LMSGetErrorString(number) {debug ("sco called LMSGetErrorString ("+number+")"); return APIFinder.LMSGetErrorString(number)+''} +function LMSGetDiagnostic(placeholder) {debug ("sco called LMSGetDiagnostic ("+placeholder+")"); return APIFinder.LMSGetDiagnostic(placeholder)+''} + +APIHolder.prototype.LMSInitialize=LMSInitialize; +APIHolder.prototype.LMSFinish=LMSFinish; +APIHolder.prototype.LMSGetValue=LMSGetValue; +APIHolder.prototype.LMSCommit=LMSCommit; +APIHolder.prototype.LMSSetValue=LMSSetValue; +APIHolder.prototype.LMSGetLastError=LMSGetLastError; +APIHolder.prototype.LMSGetErrorString=LMSGetErrorString; +APIHolder.prototype.LMSGetDiagnostic=LMSGetDiagnostic; + + Index: openacs-4/packages/lorsm/www/delivery/applet.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/applet.tcl,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/applet.tcl 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/applet.tcl 13 Aug 2007 09:20:16 -0000 1.3 @@ -13,6 +13,7 @@ } -errors { } +set menu_type [ad_get_client_property lorsm menu_type] set debuglevel [ad_get_client_property lorsm debuglevel] if {$debuglevel > 0} { set app_width 150 Index: openacs-4/packages/lorsm/www/delivery/blank-no-javascript.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/blank-no-javascript.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/blank-no-javascript.html 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,14 @@ + + + + + + +@course_name@ + - + - + - + - + - + - + - + - + - + Index: openacs-4/packages/lorsm/www/delivery/delivery.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/delivery.adp,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/lorsm/www/delivery/delivery.adp 15 May 2007 20:14:46 -0000 1.3 +++ openacs-4/packages/lorsm/www/delivery/delivery.adp 13 Aug 2007 09:20:16 -0000 1.4 @@ -4,7 +4,7 @@ @course_name@ - + Index: openacs-4/packages/lorsm/www/delivery/exit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/exit.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/lorsm/www/delivery/exit.tcl 7 Jun 2006 14:05:44 -0000 1.3 +++ openacs-4/packages/lorsm/www/delivery/exit.tcl 13 Aug 2007 09:20:16 -0000 1.4 @@ -17,7 +17,7 @@ } #set the following accordingly -set level "Notice" +set level "debug" set track_id [ad_get_client_property lorsm currenttrackid] set lorsmstudenttrack [ad_get_client_property lorsm studenttrack] @@ -40,17 +40,16 @@ ad_set_client_property lorsm currenttrackid "" ad_set_client_property lorsm studenttrack "" if { $track_id == 0 || $track_id == "" } { - ns_log $level "SCORM leaving non rte-inited (or better a rte-finished) course" + ns_log $level "delivery/exit leaving non rte-inited (or better a rte-finished) course" } else { - ns_log $level "SCORM leaving course which had been rte-inited but NOT FINISHED (user forcing exit before time) (lorsm_cmi_core.track_id=$track_id)" + ns_log $level "delivery/exit leaving course which had been rte-inited but NOT FINISHED (user forcing exit before time) (lorsm_cmi_core.track_id=$track_id)" } if { $lorsmstudenttrack == 0 || $lorsmstudenttrack == "" } { - ns_log $level "SCORM leaving non istrackable course" + ns_log $level "delivery/exit leaving non istrackable course" } else { - ns_log $level "SCORM leaving course which was either istrackable or rte-inited (lorsm_student_track.track_id=$lorsmstudenttrack" + ns_log $level "delivery/exit leaving course which was either istrackable or rte-inited (lorsm_student_track.track_id=$lorsmstudenttrack" } # redirects -ns_log Warning "RETURN $return_url" - +ns_log $level "delivery/exit $return_url" ad_returnredirect $return_url Index: openacs-4/packages/lorsm/www/delivery/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/index.adp,v diff -u -N -r1.5 -r1.6 --- openacs-4/packages/lorsm/www/delivery/index.adp 15 May 2007 20:14:46 -0000 1.5 +++ openacs-4/packages/lorsm/www/delivery/index.adp 13 Aug 2007 09:20:16 -0000 1.6 @@ -1,3 +1,3 @@ - Index: openacs-4/packages/lorsm/www/delivery/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/index.tcl,v diff -u -N -r1.10 -r1.11 --- openacs-4/packages/lorsm/www/delivery/index.tcl 17 May 2007 20:37:01 -0000 1.10 +++ openacs-4/packages/lorsm/www/delivery/index.tcl 13 Aug 2007 09:20:16 -0000 1.11 @@ -9,32 +9,46 @@ @arch-tag: 64f3397b-4558-4298-a995-fc63e472f2a1 @cvs-id $Id$ } { - menu_off:integer,notnull,optional man_id:integer,notnull + menu_off:integer,notnull,optional item_id:integer,notnull,optional ims_id:integer,notnull,optional } -properties { } -validate { } -errors { } + set debuglevel 0 +set menu_type "menu-mk" ad_set_client_property lorsm debuglevel $debuglevel +ad_set_client_property lorsm menu_type $menu_type set ses_renew [ad_parameter -package_id [ad_acs_kernel_id] SessionRenew security 300] + if { ! [info exists menu_off] } { set menu_off 0 } +set user_id [ad_conn user_id] + if { [info exists item_id] } { ad_set_client_property lorsm ims_id $item_id if { ! [info exists ims_id] } { set ims_id $item_id } } else { + if { $menu_off == 0 } { ad_set_client_property lorsm ims_id "" -# ns_log notice "UNSETTING LORSM IMS_ID '[ad_conn url]'" + ns_log notice "UNSETTING LORSM IMS_ID '[ad_conn url]'" + } else { + #given menu_off without ims_id, i have to provide a default one! + #since an ims_item_id wasn't provided, we just pick up the first one + set item_list [lorsm::get_item_list $man_id $user_id] + set ims_id [lindex $item_list 0] + ad_set_client_property lorsm ims_id $ims_id + } } if { [info exists ims_id] } { @@ -44,16 +58,22 @@ set body_url [export_vars -base "record-view" -url {item_id man_id}] } + + # Get the course name if {[db_0or1row manifest " select cp.course_name, cp.fs_package_id, isscorm, pf.folder_name, - pf.format_name + pf.format_name, + case + when upper(scorm_type) = 'SCO' then 'delivery-scorm' + else 'delivery' + end as deliverymethod from - ims_cp_manifests cp, + ims_cp_manifests cp left join (select man_id, max(scorm_type) as scorm_type from ims_cp_resources group by man_id ) as cpr using (man_id) , lorsm_course_presentation_formats pf where cp.man_id = :man_id @@ -67,16 +87,24 @@ } else { set course_name "No Course Name" } + +ns_log warning "\$isscorm=$isscorm while delivery method has to be = $deliverymethod" + if {$isscorm} { set folder_name "delivery-scorm" +} else { + # workaround for when isscorm is set to inconsisten value + # (who sets it ?) + if {$deliverymethod=="delivery-scorm"} { + set folder_name delivery-scorm + } } + set return_url [dotlrn_community::get_community_url [dotlrn_community::get_community_id]] - # Student tracking set package_id [ad_conn package_id] set community_id [dotlrn_community::get_community_id] -set user_id [ad_conn user_id] ad_set_client_property lorsm currentcourse $man_id @@ -112,7 +140,11 @@ ## FIXME -db_1row get_format "select folder_name, isscorm from lorsm_course_presentation_formats f, ims_cp_manifests m where f.format_id=m.course_presentation_format and m.man_id=:man_id" -if {$isscorm} { - set folder_name delivery-scorm -} +#db_1row get_format "select folder_name, isscorm from lorsm_course_presentation_formats f, ims_cp_manifests m where f.format_id=m.course_presentation_format and m.man_id=:man_id" +#if {$isscorm} { +# set folder_name delivery-scorm +#} + +ad_set_client_property lorsm deliverymethod $folder_name + +ns_log debug "delivery/index.tcl returning with folder_name $folder_name" Index: openacs-4/packages/lorsm/www/delivery/lmsfinish.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/lmsfinish.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/lmsfinish.adp 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,106 @@ + + + + +SCORM FINISHER + + + + +I will send you to: +the new item_id is @item_id@, while the old one is @initedonpage@ + + + + + Index: openacs-4/packages/lorsm/www/delivery/lmsfinish.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/lmsfinish.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/lmsfinish.tcl 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,27 @@ +# packages/lorsm/www/delivery-scorm/lmsfinish.tcl + +ad_page_contract { + + called if an user is swithing between items of the same manifest, + WITHOUT the content having previously called LMSFinish + + @author Michele Slocovich () + @creation-date 2004-07-04 +} { + item_id:optional,integer,notnull + man_id:integer,notnull + initedonpage:integer,notnull +} -properties { +} -validate { +} -errors { +} + +if { ! [info exists item_id] } { + set item_id 0 +} + +#this should automatically happen. nevertheless we put it here +#ad_set_client_property lorsm studenttrack "" +#ad_set_client_property lorsm currenttrackid "" +#ad_set_client_property lorsm initedonpage "" + Index: openacs-4/packages/lorsm/www/delivery/menu-mk.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu-mk.adp,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/menu-mk.adp 15 May 2007 20:14:46 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/menu-mk.adp 13 Aug 2007 09:20:16 -0000 1.3 @@ -2,80 +2,82 @@ - - - - - #lorsm.Exit_Course#
#lorsm.return_to_LRN#
-  - + +
+


+
+ +

+
    +
  • @tree_items.icon;noquote@ + @tree_items.label@ + +
  • -
- - + + + + + +Menu not available. + +
+ \ No newline at end of file Index: openacs-4/packages/lorsm/www/delivery/menu-mk.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu-mk.tcl,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/menu-mk.tcl 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/menu-mk.tcl 13 Aug 2007 09:20:16 -0000 1.3 @@ -1,4 +1,4 @@ -# packages/lorsm/www/delivery/index.tcl +# packages/lorsm/www/delivery/menu-mk.tcl ad_page_contract { @@ -11,48 +11,76 @@ } { man_id:integer,notnull ims_id:integer,notnull,optional - track_id:integer,notnull + menu_off:integer,notnull,optional + track_id:integer,notnull,optional } -properties { } -validate { } -errors { } +if { ![info exists track_id] } { + set track_id 0 } +if { ![info exists menu_off] } { + set menu_off 0 } + +set debuglevel [ad_get_client_property lorsm debuglevel] +set deliverymethod [ad_get_client_property lorsm deliverymethod] + +if { [string equal $deliverymethod "delivery-scorm"] } { + set rte true +} else { + set rte false +} + + set items_list [list] set control_list [list] +set target "content" -set org_id [db_string get_org_id { select org_id from ims_cp_organizations where man_id = :man_id} ] -# We need all the count of all items (just live revisions) -set items_count [db_string get_items_count { select count(ims_item_id) - from ims_cp_items where ims_item_id in ( select live_revision - from cr_items where content_type = 'ims_item_object') and - org_id = :org_id -}] +#set org_id [db_string get_org_id { select org_id from ims_cp_organizations where man_id = :man_id} ] -# Get the root items -set count 0 -db_foreach get_root_item { select ims_item_id from ims_cp_items where parent_item = :org_id and org_id = :org_id } { - lappend items_list [list $ims_item_id 1] - lappend control_list $ims_item_id - incr count -} -template::multirow create tree_items link label indent last_indent target - -while { $count < $items_count } { - foreach item $items_list { - set item_id [lindex $item 0] - set indent [expr [lindex $item 1] + 1] - db_foreach get_items { select ims_item_id from ims_cp_items where parent_item = :item_id and org_id = :org_id } { - if { [string equal [lsearch -exact $control_list $ims_item_id] "-1"] } { - lappend items_list [list $ims_item_id $indent] - lappend control_list $ims_item_id - incr count - } +#we handle multiple orgs +foreach org_id [db_list get_org_id { } ] { + set count 0 + lappend items_list [list $org_id 0] + foreach item [lorsm::get_items_indent -org_id $org_id] { + #we shift everything to the right to get the orgs inserted there + set indent [expr [lindex $item 1] +1 ] + set item_id [lindex $item 0] + set item [list $item_id $indent] + lappend items_list $item } - } + # We need all the count of all items (just live revisions) + set items_count [db_string get_items_count { select count(ims_item_id) + from ims_cp_items where ims_item_id in ( select live_revision + from cr_items where content_type = 'ims_item_object') and + org_id = :org_id + }] + # Get the root items + db_foreach get_root_item { select ims_item_id from ims_cp_items where parent_item = :org_id and org_id = :org_id } { + #lappend items_list [list $ims_item_id 1] + #lappend control_list $ims_item_id + incr count + } + while { $count < $items_count } { + foreach item $items_list { + set item_id [lindex $item 0] + set indent [expr [lindex $item 1] + 1] + db_foreach get_items { select ims_item_id from ims_cp_items where parent_item = :item_id and org_id = :org_id } { + if { [string equal [lsearch -exact $control_list $ims_item_id] "-1"] } { + #this duplicates ITEMS lappend items_list [list $ims_item_id $indent] + #lappend control_list $ims_item_id + incr count + } + } + } + } } +template::multirow create tree_items icon link label indent last_indent target + set community_id [dotlrn_community::get_community_id] set counter 1 set user_id [ad_conn user_id] @@ -97,15 +125,15 @@ # Another item in the same level, just add to the list lappend TREE_HASH "TREE_HASH\[\"ims_id.$item_id\"\] = $counter;" lappend levelitems "\['$title', $url\]" - template::multirow append tree_items $url $title $level + template::multirow append tree_items "SAMELEVEL" $url $title $level incr counter } elseif { $level < $nextlevel } { # Next item is a sub-item set ocounter $counter incr counter set submenu "[generate_tree_menu $items $index [expr $rlevel + 1]]" lappend TREE_HASH "TREE_HASH\[\"ims_id.$item_id\"\] = $ocounter;" - template::multirow append tree_items $url $title $level + template::multirow append tree_items "NEXTLEVEL" $url $title $level if { [llength $submenu] } { # There's a submenu lappend levelitems \ @@ -143,7 +171,7 @@ return [list] } else { lappend TREE_HASH "TREE_HASH\[\"ims_id.$item_id\"\] = $counter;" - template::multirow append tree_items $url $title $level + template::multirow append tree_items "LEAF" $url $title $level incr counter return [join \ [lappend levelitems \ @@ -187,31 +215,32 @@ order by org_id } { - + #trying to visualize organizations + lappend js [list 0 $org_id $org_title $man_id "ims/organization" ""] + db_foreach sql { - SELECT - -- (tree_level(ci.tree_sortkey) - :indent) as indent, - i.parent_item, - i.ims_item_id, - i.item_title as item_title, - cr.mime_type - FROM - acs_objects o, ims_cp_items i, cr_items ci, cr_revisions cr, - ims_cp_items_map im - WHERE - o.object_type = 'ims_item_object' - AND - i.org_id = :org_id - AND - o.object_id = i.ims_item_id - AND - i.ims_item_id = im.ims_item_id - and im.man_id=:man_id - and im.org_id=:org_id - and im.hide_p='f' - and im.community_id=:community_id - and ci.item_id=cr.item_id - and cr.revision_id=i.ims_item_id + SELECT + -- (tree_level(ci.tree_sortkey) - :indent ) as indent, + i.parent_item, + i.ims_item_id, + i.item_title as item_title, + i.prerequisites_s as prerequisites, + cr.mime_type + FROM + acs_objects o, ims_cp_items i, cr_items ci, cr_revisions cr, + ims_cp_manifest_class im + WHERE + o.object_type = 'ims_item_object' + AND + i.org_id = :org_id + AND + o.object_id = i.ims_item_id + AND + im.man_id=:man_id + and im.isenabled='t' + and im.community_id=:community_id + and ci.item_id=cr.item_id + and cr.revision_id=i.ims_item_id AND EXISTS @@ -228,7 +257,7 @@ set item_id [lindex $item 0] set indent [lindex $item 1] if { [string equal $item_id $ims_item_id] } { - lappend js [list $indent $ims_item_id $item_title $man_id $mime_type] + lappend js [list $indent $ims_item_id $item_title $man_id $mime_type $prerequisites] } } } @@ -237,11 +266,187 @@ if { [info exists js] } { set last_indent 1 foreach l $js { - foreach {indent item_id title man_id mime_type} $l {break} - template::multirow append tree_items [export_vars -base "record-view" \ - -url {item_id man_id}] "$title $mime_type" $indent $last_indent + foreach {indent item_id title man_id mime_type prerequisites} $l {break} + + #analyzing LESSON STATUS for the ITEM + #this could as well become a lorsm:scorm:function + + ns_log debug "MENU-MK tree : $indent $item_id $title " + + if { ! [string equal $mime_type "ims/organization"] } { + + if { [ db_0or1row isnotanemptyitem "select res_id + from ims_cp_items_to_resources + where ims_item_id= $item_id + limit 1" ] } { + set icon "" + } else { + #since the item has no elements it's a placeholder, we assume it's a folder. + #time will tell if the assumption is correct. + set icon "\"Folder\"" + } + + if { ! [ db_0or1row isanysuspendedsession "select lorsm.track_id as track_id, + cmi.lesson_status as lesson_status from + lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $man_id + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $man_id + and + cmi.item_id = $item_id + order by + lorsm.track_id desc + limit 1" ] } { + #item has no track for the user + #the icon should be the same as per "not yet visited" + append icon "\"Not" + } else { + switch -regexp $lesson_status { + null { append icon "\"Not" } + incomplete { append icon "\"Incomplete\"" } + complete { append icon "\"Completed\"" } + failed { append icon "\"Failed\"" } + "not attempted" { append icon "\"Not" } + passed { append icon "\"Passed\"" } + default { append icon " $lesson_status ** \"$lesson_status\""} + } + } + + + #we analize now prerequisites. + + #regsub -all {&} $prerequisites " " prerequisites + regsub -all {[\{\}]} $prerequisites "" prerequisites + regsub -all { & } $prerequisites " " prerequisites + set prerequisites_list [split $prerequisites] + + foreach prer $prerequisites_list { + if { ! [empty_string_p $prer] } { + ns_log debug "MENU prerequisites for $item_id are $prer " + #in the following query we disregard the organization + if { ! [ db_0or1row givemeid "select i.ims_item_id as id_from_ref + from + ims_cp_items i, + ims_cp_manifest_class im, + ims_cp_organizations o + WHERE + i.identifier=:prer + + AND + o.org_id = i.org_id + AND + o.man_id = :man_id + AND + im.man_id= :man_id + AND + im.isenabled='t' + AND + im.community_id=:community_id" + ] } { + ns_log warning "MENU-MK: prerequisites not found comm: $community_id, man: $man_id, org: $org_id, item: $item_id" + continue + } else { + ns_log debug "THE REQUIRED ITEM IS $id_from_ref "; + } + } + if { ! [empty_string_p $id_from_ref] } { + ns_log debug "MENU prerequisites for $item_id are $id_from_ref" + if { ! [ db_0or1row isanysuspendedsession " + select lorsm.track_id as track_id, cmi.lesson_status as lex_status + from lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $man_id + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $man_id + and + cmi.item_id = $id_from_ref + order by + lorsm.track_id desc + " ] } { + ns_log debug "NOT FOUND TRACK" + append icon "\"Missing" + } else { + ns_log debug "ITEM ID $id_from_ref HAS A TRACK WITH $lex_status" + switch -regexp $lex_status { + null { append icon "\"Missing" } + incomplete { append icon "\"Missing" } + failed { append icon "\"Missing" } + "not attempted" { append icon "\"Missing" } + passed { append icon "\"Prerequisite" } + complete { append icon "\"Prerequisite" } + default { append icon " $lesson_status ** \"$lesson_status\""} + } + } + #if found session for id_from_ref + } + #if found id_from_ref + } + #foreach close + + template::multirow append tree_items $icon [export_vars -base "record-view" \ + -url {item_id man_id}] "$title $mime_type" $indent $last_indent $target set last_indent $indent + + } else { + + regsub -all {[\{\}]} $title "" title + + set icon "\"Content" + + if { ! [ db_0or1row isanysuspendedsession " + select lorsm.track_id as track_id, cmi.lesson_status as lesson_status + from lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $man_id + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $man_id + and + cmi.item_id = $item_id + order by + lorsm.track_id desc + " ] } { + ns_log debug "Menu-mk: no org tracking found" + + append icon "\"Not" + } else { + switch -regexp $lesson_status { + null { append icon "\"Not" } + incomplete { append icon "\"Incomplete\"" } + complete { append icon "\"Completed\"" } + failed { append icon "\"Failed\"" } + "not attempted" { append icon "\"Not" } + passed { append icon "\"Passed\"" } + default { append icon " $lesson_status ** \"$lesson_status\""} + } + } + + set last_indent $indent + template::multirow append tree_items $icon "" $title $indent $last_indent "" + + set last_indent $indent + + } } } # return_url set return_url [dotlrn_community::get_community_url [dotlrn_community::get_community_id]] + Index: openacs-4/packages/lorsm/www/delivery/menu-mk.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu-mk.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/menu-mk.xql 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,45 @@ + + + + + + select + org_id + from + ims_cp_organizations + where + man_id = :man_id + + + + + + select + org.org_id, + org.org_title as org_title, + org.hasmetadata, + tree_level(o.tree_sortkey) as indent + from + ims_cp_organizations org, acs_objects o + where + org.org_id = o.object_id + and + man_id = :man_id + order by + org_id + + + + + + select + fs_package_id + from + ims_cp_manifests + where + man_id = :man_id + + + + + \ No newline at end of file Index: openacs-4/packages/lorsm/www/delivery/menu.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu.adp,v diff -u -N -r1.5 -r1.6 --- openacs-4/packages/lorsm/www/delivery/menu.adp 7 Jun 2006 14:05:44 -0000 1.5 +++ openacs-4/packages/lorsm/www/delivery/menu.adp 13 Aug 2007 09:20:16 -0000 1.6 @@ -1,323 +1,75 @@ - - - - - - - - - - - - - - - -
-
- -
-
- - - - -
- -debug is: ON - - - - + + + + + + + + + + + + + + + + + +
+ + debug is: ON
+ delivery is: @deliverymethod@ +
+
+ +
+
+ +
+
+ + + + + + Index: openacs-4/packages/lorsm/www/delivery/menu.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/menu.js 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,274 @@ + +var menu=null; +//var API; +ns4 = (document.layers)? true:false; +ie4 = (document.all)? true:false; + +//function onunload() { +//alert("unloading me"); +//z=parent.closecontents(); +//if (this.parent.content.window.location.href != "blank.htm") { +// setTimeout("onunload();",1000) +// } +//} + +function selfcheck() { + //alert(parent.window.name); + if ( parent.window.name=='LRN_delivery_window' ) { + parent.close(); + } +} + +function debug(message) { + if (debuglevel==1) { + try { + parent.frames['talk'].document.write(" menu.adp : "+message+"
"); + } catch (err) { + //alert("no talk ? no party!"); + } + } + return; + } + +function menu_init() { + //Called during LOAD for the menu to see if applet is there + //API = this.document.APIAdapter; + if(!self.parent.window.frames['AppletContainerFrame'].APIFinder) { + debug("menu_init: before systemcheck"); + z=systemcheck(); + debug("menu_init: after systemcheck"); + try { + if(self.parent.window.frames['AppletContainerFrame'].initialized) { + debug("menu_init: WARNING menu reload while initialized ??? "); + this.toggleBox('menudiv',0); + } else { + debug("menu_init: We are not within LMS dialogue (this is good)"); + } + } catch (err) { + debug("Applet not available in menu.init();"); + } + //document.applets[0].init(); + //alert("JAVA-JAVASCRIPT: i've inited myself"); + } else { + debug("appletframe APIFinder found: it's just a menu reload."); + this.toggleBox('menudiv',1); + } +} + + +function writit(text,id) +{ + if (document.getElementById) //Gecko IE5+ + { + x = document.getElementById(id); + x.innerHTML = ''; + x.innerHTML = text; + } + else if (document.all) // IE 4 + { + x = document.all[id]; + x.innerHTML = text; + } + else if (document.layers) //NN4+ + { + x = document.layers[id]; + text2 = '

' + text + '

'; + x.document.open(); + x.document.write(text2); + x.document.close(); + } +} + +function toggleBox(szDivID, iState) // 1 visible, 0 hidden +{ + if(document.layers) //NN4+ + { + document.layers[szDivID].visibility = iState ? "show" : "hide"; + } + else if(document.getElementById) //gecko(NN6) + IE 5+ + { + var obj = document.getElementById(szDivID); + obj.style.visibility = iState ? "visible" : "hidden"; + } + else if(document.all) // IE 4 + { + document.all[szDivID].style.visibility = iState ? "visible" : "hidden"; + } +} + +function show(id) { + if (ns4) document.layers[id].visibility="view"; + if (ie4) document.all[id].style.visibility = "visible"; +} + +function hide(id) { + if (ns4) document.layers[id].visibility = "hide"; + if (ie4) document.all[id].style.visibility = "hidden"; +} + +function changeSCOContent() { + alert("LMSFINISH completing: getting out on JAVA APPLET request"); + parent.window.location.href = this.return_url; + return 1; +} + +/* function showmenu() { + debug("within showmenu"); + // if(isNull(document.getElementById("treemenu").style.display)) { + debug("showmenu is null !!!"); + // } else { + debug("not showing"); + // NON SUPPORTATO IN IE5.01 + // document.getElementById("treemenu").style.display='block'; + // } +} + */ + +function showcontent() { + parent.frames['content'].location.href = this.record_view_url; +} + +function closeme() { + parent.window.close(); +} + +// function getCookie(name) +// { + // alert("getCookie"); + // var dc = document.cookie; + // var prefix = name + "="; + // var begin = dc.indexOf("; " + prefix); + // if (begin == -1) + // { + // begin = dc.indexOf(prefix); + // if (begin != 0) return null; + // } + // else + // { + // begin += 2; + // } + // var end = document.cookie.indexOf(";", begin); + // if (end == -1) + // { + // end = dc.length; + // } + // return (name+"="+unescape(dc.substring(begin + prefix.length, end)).replace("+"," ").replace("+"," ").replace("+"," ").replace("+"," ")); +// } + + +var tree_tpl = { + 'target' : 'content', // name of the frame links will be opened in + + 'icon_e' : 'tigra/demo1/icons/empty.gif', // empty image + 'icon_l' : 'tigra/demo1/icons/line.gif', // vertical line + + 'icon_32' : 'tigra/demo1/icons/base.gif', // root leaf icon normal + 'icon_36' : 'tigra/demo1/icons/base.gif', // root leaf icon selected + + 'icon_48' : 'tigra/demo1/icons/base.gif', // root icon normal + 'icon_52' : 'tigra/demo1/icons/base.gif', // root icon selected + 'icon_56' : 'tigra/demo1/icons/base.gif', // root icon opened + 'icon_60' : 'tigra/demo1/icons/base.gif', // root icon selected + + 'icon_16' : 'tigra/demo1/icons/folder.gif', // node icon normal + 'icon_20' : 'tigra/demo1/icons/folderopen.gif', // node icon selected + 'icon_24' : 'tigra/demo1/icons/folderopen.gif', // node icon opened + 'icon_28' : 'tigra/demo1/icons/folderopen.gif', // node icon selected opened + + 'icon_0' : 'tigra/demo1/icons/page.gif', // leaf icon normal + 'icon_4' : 'tigra/demo1/icons/page.gif', // leaf icon selected + + 'icon_2' : 'tigra/demo1/icons/joinbottom.gif', // junction for leaf + 'icon_3' : 'tigra/demo1/icons/join.gif', // junction for last leaf + 'icon_18' : 'tigra/demo1/icons/plusbottom.gif', // junction for closed node + 'icon_19' : 'tigra/demo1/icons/plus.gif', // junctioin for last closed node + 'icon_26' : 'tigra/demo1/icons/minusbottom.gif',// junction for opened node + 'icon_27' : 'tigra/demo1/icons/minus.gif' // junctioin for last opended node +}; + +function openMenu( ims_id ) { + if (ims_id.n_depth > 0) { + openMenu(ims_id.o_parent); + if ( ! ims_id.b_opened ) + trees[ims_id.o_root.n_id].toggle(ims_id.n_id); + } else { + return; + } +} + +function selectItem( index ) { + openMenu ( menu.a_index[index] ); + trees[menu.a_index[index].o_root.n_id].select(menu.a_index[index].n_id); +} + +function seekAndDestroy( ims_id ) { + // Traverse the tree until we reach level 1 + if ( ims_id.b_opened ) { + seekAndDestroy(ims_id.o_parent); + + // Loop through this level and close all other opened items + for(var i=0; i
Failed system configuration test
Please check requirements"); + parent.frames['content'].document.write("
This window will now close."); + setTimeout("closeme();",12000) + } else { + + //stimulating the applet container back to the initial. + parent.frames['AppletContainerFrame'].location.href = this.applet_url; + + if((AppletContainerFrame.megatries<4)) { + parent.frames['content'].document.write("
Please wait. Checking system configuration
"); + } else { + parent.frames['content'].document.write("

Failed system configuration test
Please check requirements"); + parent.frames['content'].document.write("
This window will now close."); + setTimeout("closeme();",12000) + } + } + } + return; +} + + Index: openacs-4/packages/lorsm/www/delivery/menu.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/menu.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/lorsm/www/delivery/menu.tcl 15 May 2007 20:14:46 -0000 1.8 +++ openacs-4/packages/lorsm/www/delivery/menu.tcl 13 Aug 2007 09:20:16 -0000 1.9 @@ -1,4 +1,4 @@ -# packages/lorsm/www/delivery/index.tcl +# packages/lorsm/www/delivery/menu.tcl ad_page_contract { @@ -12,14 +12,29 @@ man_id:integer,notnull ims_id:integer,notnull,optional menu_off:integer,notnull,optional - track_id:integer,notnull + track_id:integer,notnull,optional } -properties { } -validate { } -errors { } +if { ![info exists track_id] } { + set track_id 0 } + +if { ![info exists menu_off] } { + set menu_off 0 } + set debuglevel [ad_get_client_property lorsm debuglevel] +set deliverymethod [ad_get_client_property lorsm deliverymethod] + +if { [string equal $deliverymethod "delivery-scorm"] } { + set rte true +} else { + set rte false +} + set items_list [list] + foreach org_id [db_list get_org_id { } ] { foreach item [lorsm::get_items_indent -org_id $org_id] {lappend items_list $item} } @@ -29,10 +44,8 @@ set community_id [dotlrn_community::get_community_id] set counter 1 set user_id [ad_conn user_id] -if { ![info exists menu_off] } { - set menu_off 0 -} + proc generate_tree_menu { items index rlevel } { # This function is recursive @@ -163,15 +176,14 @@ } db_foreach sql { SELECT - i.parent_item, - i.ims_item_id, - i.item_title as item_title + i.ims_item_id, + i.item_title as item_title FROM - ims_cp_items i, cr_items ci, cr_revisions cr - WHERE - i.org_id = :org_id - AND ci.item_id=cr.item_id + ims_cp_items i, cr_items ci, cr_revisions cr + WHERE + i.org_id = :org_id + AND ci.item_id=cr.item_id AND cr.revision_id=i.ims_item_id AND EXISTS (select 1 from acs_object_party_privilege_map p @@ -187,8 +199,6 @@ } } - - if { [info exists js] } { set index 0 set TREE_ITEMS [generate_tree_menu $js $index 1] Index: openacs-4/packages/lorsm/www/delivery/popup.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/popup.adp,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/popup.adp 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/popup.adp 13 Aug 2007 09:20:16 -0000 1.3 @@ -252,7 +252,7 @@ } function init() { - this.childwindow=popit('popup','popup2?man_id=@man_id@&ims_id=@ims_id@&track_id=@track_id@&menu_off=@menu_off@ ',810,540,20,20); + this.childwindow=popit('popup','popup2?man_id=@man_id@&ims_id=@ims_item_id@&track_id=@track_id@&menu_off=@menu_off@ ',810,540,20,20); this.debugwindow=popit('debuggerwindow','blank.html',210,640,10,10); @@ -343,7 +343,7 @@ //chiamata quando trovato adapter childwindow.frames['content'].window.location.href = "blank.html"; -childwindow.frames['content'].window.location.href = "@body_url;noquote@body?man_id=@man_id@"; +childwindow.frames['content'].window.location.href = "@body_url;noquote@body?man_id=@man_id@"; //not ready yet to show menu //debug(typeof(this.childwindow)); @@ -372,9 +372,9 @@ KeepAlive(); childwindow.frames['content'].document.location.href = "blank.html"; - childwindow.frames['content'].document.location.href = "@body_url;noquote@body?man_id=@man_id@"; + childwindow.frames['content'].document.location.href = "@body_url;noquote@body?man_id=@man_id@"; //let's show menu now - childwindow.frames['menu'].document.location.href = "menu?man_id=@man_id@&ims_id=@ims_id@&track_id=@track_id@&menu_off=@menu_off@"; + childwindow.frames['menu'].document.location.href = "menu?man_id=@man_id@&ims_id=@ims_item_id@&track_id=@track_id@&menu_off=@menu_off@"; //obviously no menu if menu is off... @@ -387,10 +387,10 @@ myTimer=setTimeout("refreshFrame()",2500); return(0); } - childwindow.frames['content'].document.location.href = "record-view?man_id=@man_id@&item_id=@item_id@"; + childwindow.frames['content'].document.location.href = "record-view?man_id=@man_id@&item_id=@ims_item_id@"; childwindow.caller=self; childwindow.focus(); - debug("calling @man_id@ with @item_id@"); + debug("calling @man_id@ with @ims_item_id@"); if (findgetAppletInfo> 7) { debug("I cannot talk to APIAdapter: try reloading me. Please notify support of your sw configuration ;) "); @@ -441,7 +441,6 @@ - name="APIAdapter"> - + Index: openacs-4/packages/lorsm/www/delivery/popup.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/popup.tcl,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/popup.tcl 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/popup.tcl 13 Aug 2007 09:20:16 -0000 1.3 @@ -4,10 +4,9 @@ @arch-tag: 64f3397b-4558-4298-a995-fc63e472f2a1 @cvs-id $Id$ } { - item_id:integer,notnull,optional + ims_item_id:integer,notnull,optional menu_off:integer,notnull,optional man_id:integer,notnull - ims_id:integer,notnull,optional } -properties { } -validate { } -errors { @@ -16,6 +15,8 @@ set debuglevel 0 ad_set_client_property lorsm debuglevel $debuglevel +#we are in a popup aren't we ? +set menu_off 1 #keepalive and debug would require this set random [clock seconds] @@ -25,24 +26,20 @@ set cookie [ad_get_cookie ad_session_id] set track_id [ad_get_client_property lorsm studenttrack] -set menu_off 1 - # Student tracking set package_id [ad_conn package_id] set community_id [dotlrn_community::get_community_id] set user_id [ad_conn user_id] -if { [info exists ims_id] } { - ns_log Notice "APPLET.TCL: ims_id is $ims_id" - set body_url [export_vars -base "record-view" -url {item_id man_id}] -} else { - if { ! [empty_string_p $item_id] } { - ns_log Notice "APPLET.TCL: item_id is $item_id" - set ims_id $item_id - set body_url [export_vars -base "record-view" -url {item_id man_id}] - } +if { ! [info exists ims_item_id] } { + #since an ims_item_id wasn't provided, we just pick up the first one + set item_list [lorsm::get_item_list $man_id $user_id] + set ims_item_id [lindex $item_list 0] } +ns_log Notice "POPUP.TCL: ims_id is $ims_item_id" +set body_url [export_vars -base "record-view" -url {ims_item_id man_id}] + # return_url set return_url [dotlrn_community::get_community_url [dotlrn_community::get_community_id]] Index: openacs-4/packages/lorsm/www/delivery/popup2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/popup2.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/popup2.adp 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,37 @@ + + + +@course_name@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: openacs-4/packages/lorsm/www/delivery/popup2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/popup2.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/delivery/popup2.tcl 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,72 @@ +# packages/lorsm/www/delivery4/index.tcl + +ad_page_contract { + + New index file using new tree menu + + @author Roel Canicula (roelmc@info.com.ph) + @creation-date 2004-08-07 + @arch-tag: 64f3397b-4558-4298-a995-fc63e472f2a1 + @cvs-id $Id: popup2.tcl,v 1.2 2007/08/13 09:20:16 emmar Exp $ +} { + menu_off:integer,notnull,optional + man_id:integer,notnull + item_id:integer,notnull,optional + ims_id:integer,notnull,optional +} -properties { +} -validate { +} -errors { +} + +set debuglevel [ ad_get_client_property lorsm debuglevel ] +set menu_off 1 + +if { [info exists item_id] } { + ad_set_client_property lorsm ims_id $item_id + if { ! [info exists ims_id] } { + set ims_id $item_id + } +} + +if { [info exists ims_id] } { + set item_id $ims_id + ad_set_client_property lorsm ims_id $ims_id + set body_url [export_vars -base "record-view" -url {item_id man_id}] +} + +# Get the course name +if {[db_0or1row manifest " + select + cp.course_name, + cp.fs_package_id + from + ims_cp_manifests cp + where + cp.man_id = :man_id + and cp.parent_man_id = 0"]} { + + # Course Name + if {[empty_string_p $course_name]} { + set course_name "No Course Name" + } +} else { + set course_name "No Course Name" +} + +# Student tracking +set package_id [ad_conn package_id] +set community_id [dotlrn_community::get_community_id] +set user_id [ad_conn user_id] +ad_set_client_property lorsm currentcourse $man_id + + +if {[lorsm::track::istrackable -course_id $man_id -package_id $package_id]} { + set track_id [lorsm::track::new \ + -user_id $user_id \ + -community_id $community_id \ + -course_id $man_id] + ad_set_client_property lorsm studenttrack $track_id +} else { + set track_id 0 + ad_set_client_property lorsm studenttrack 0 +} Index: openacs-4/packages/lorsm/www/delivery/record-view.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/record-view.tcl,v diff -u -N -r1.13 -r1.14 --- openacs-4/packages/lorsm/www/delivery/record-view.tcl 15 May 2007 20:14:46 -0000 1.13 +++ openacs-4/packages/lorsm/www/delivery/record-view.tcl 13 Aug 2007 09:20:16 -0000 1.14 @@ -1,4 +1,5 @@ # packages/lorsm/www/delivery4/record-view.tcl + ad_page_contract { records a view for this ims_cp_item and redirects to its url @@ -9,74 +10,64 @@ @arch-tag: a7aba567-c4c1-4f1c-b5f3-ebc1ab277515 @cvs-id $Id$ } { - item_id:notnull - man_id:notnull + item_id:integer,notnull + man_id:integer,notnull + lmsfinish:integer,optional } -properties { } -validate { } -errors { } +if { ! [info exists lmsfinish] } { + set lmsfinish 0 +} set viewer_id [ad_conn user_id] - set views [views::record_view -object_id $item_id -viewer_id $viewer_id] - set ns_item_id $item_id set revision_id $item_id +#we check for those "escaping" sessions without doing LMSFINISH +set currenttrackid [ad_get_client_property lorsm currenttrackid] +set lorsmstudenttrack [ad_get_client_property lorsm studenttrack] +set initedonpage [ad_get_client_property lorsm initedonpage] -ad_set_client_property lorsm ims_id $item_id -ad_set_client_property lorsm man_id $man_id -set item_id [lorsm::delivery::get_item_id -revision_id $revision_id] +if { $initedonpage!=0 && $initedonpage!="" } { + if { $lmsfinish > 0 } { + ns_log warning "SCORM : back to record view after lms finish, but it hasn't worked!" + ns_log warning "SCORM : resetting all visiting parameters." + ad_set_client_property lorsm studenttrack 0 + ad_set_client_property lorsm studenttrack "" + ad_set_client_property lorsm currenttrackid "" + ad_set_client_property lorsm initedonpage "" + } else { + ad_set_client_property lorsm studenttrack 0 + ns_log warning "SCORM : new content item with still open course ???" + ns_log warning "SCORM : we call for LMSFinish in place of the content!!!!!!???" + ad_returnredirect [export_vars -base lmsfinish {item_id man_id initedonpage} ] + } +} +#set item_id [lorsm::delivery::get_item_id -revision_id $revision_id] + set folder_id [lorsm::delivery::get_folder_id_from_man_id -man_id $man_id] set lors_root [lorsm::get_root_folder_id] set folder_name [lorsm::delivery::get_folder_name -folder_id $folder_id] set content_root [lorsm::delivery::get_item_id_from_name_parent -name $folder_name -parent_id $lors_root] -#ns_log notice "record-view folder_id='${folder_id}' lors_root='${lors_root}' folder_name='${folder_name}' content_root='${content_root}'" + if {[empty_string_p $content_root]} { # This was uploaded with lorsm so we use the folder_id from the table set content_root [lorsm::delivery::get_folder_id_from_man_id -man_id $man_id] } -#ns_log notice "record-view content_root='${content_root}'" set url2 $folder_name # Get the href of the item set href [lorsm::delivery::get_href -ims_item_id $revision_id] -# handle regular acs_object here since it's not stored in the CR -set type [db_string get_type "select type from ims_cp_resources r, ims_cp_items_to_resources i2r where i2r.ims_item_id=:revision_id and i2r.res_id=r.res_id" -default webcontent] - # Get the item title set item_title [lorsm::delivery::get_ims_item_title -ims_item_id $revision_id] -ns_log notice "lorsm record-viw.tcl type='${type}'" -switch -glob -- $type { - as_sections { - # FIXME stupidly assume that a section can only be in one assessment - set section_item_id [string trimleft $href "/o/"] - db_1row get_assessment_id "select ci.item_id as assessment_id, m.section_id from as_assessment_section_map m, cr_items ci, cr_items ci2 where ci.latest_revision = m.assessment_id and m.section_id=ci2.latest_revision and ci2.item_id=:section_item_id" -# rp_form_put assessment_id $assessment_id -# ad_return_complaint 1 "assessment_id = '${assessment_id}' section_id='${section_id}'" - ad_returnredirect [export_vars -base ../../assessment/assessment {assessment_id {single_section_id $section_id}}] - ad_script_abort - } - ::xowiki::* { - set form [rp_getform] - ns_set delkey $form item_id - rp_form_put template_file view-plain - rp_form_put __include_vars [list item_id [string trimleft $href "/o/"] css ""] - rp_form_put __include /packages/xowiki/lib/view - db_1row get_format "select folder_name as delivery_folder_name, isscorm from lorsm_course_presentation_formats f, ims_cp_manifests m where f.format_id=m.course_presentation_format and m.man_id=:man_id" - if {$isscorm} { - set delivery_folder_name delivery-scorm - } - rp_internal_redirect "/packages/lorsm/www/delivery/${delivery_folder_name}" - } - default { set cr_item_id [lors::cr::get_item_id -folder_id $content_root -name $href] - - if { [empty_string_p $cr_item_id] } { set res_id [lorsm::delivery::get_res_id -ims_item_id $revision_id] if { ![empty_string_p $res_id] } { @@ -101,54 +92,181 @@ # Else deliver the page if { ![empty_string_p $cr_item_id] } { + # we check if the user has access right to the item + #we analize now prerequisites. - the logic is identical to menu. + set community_id [dotlrn_community::get_community_id] + set user_id [ad_conn user_id] + + db_1row getitemattributes "select i.parent_item, + i.ims_item_id, + i.item_title as item_title, + i.prerequisites_s as prerequisites, + cr.mime_type + FROM + acs_objects o, ims_cp_items i, cr_items ci, cr_revisions cr, + ims_cp_manifest_class im, ims_cp_organizations org + WHERE + o.object_type = 'ims_item_object' + AND + i.org_id = org.org_id + AND + o.object_id = i.ims_item_id + AND + im.man_id=:man_id + and + i.ims_item_id=:revision_id + and im.isenabled='t' + and im.community_id=:community_id + and ci.item_id=cr.item_id + and cr.revision_id=i.ims_item_id + " + + #regsub -all {&} $prerequisites " " prerequisites + regsub -all {[\{\}]} $prerequisites "" prerequisites + regsub -all { & } $prerequisites " " prerequisites + set prerequisites_list [split $prerequisites] + + foreach prer $prerequisites_list { + if { ! [empty_string_p $prer] } { + ns_log warning "MENU prerequisites for $item_id are $prer " + #in the following query we disregard the organization + if { ! [ db_0or1row givemeid "select i.ims_item_id as id_from_ref, i.item_title as id_from_ref_title + from + ims_cp_items i, + ims_cp_manifest_class im, + ims_cp_organizations o + WHERE + i.identifier=:prer + AND + o.org_id = i.org_id + AND + o.man_id = :man_id + AND + im.man_id= :man_id + AND + im.isenabled='t' + AND + im.community_id=:community_id" + ] } { + ns_log warning "RECORD_VIEW: prerequisites not found comm: $community_id, man: $man_id, item: $item_id" + continue + } else { + ns_log debug "RECORD_VIEW: THE REQUIRED ITEM IS $id_from_ref " + } + } + if { ! [empty_string_p $id_from_ref] } { + ns_log warning "RECORD_VIEW: prerequisites for $item_id are $id_from_ref" + if { ! [ db_0or1row isanysuspendedsession " + select lorsm.track_id as track_id, cmi.lesson_status as lex_status + from lorsm_student_track lorsm, lorsm_cmi_core cmi + where + lorsm.user_id = $user_id + and + lorsm.community_id = $community_id + and + lorsm.course_id = $man_id + and + lorsm.track_id = cmi.track_id + and + cmi.man_id = $man_id + and + cmi.item_id = $id_from_ref + order by + lorsm.track_id desc + " ] } { + ns_log warning "RECORD_VIEW: NOT FOUND TRACK" + append errormessage "Not attempted : $id_from_ref_title ($id_from_ref)" + append errormessage "
" + ns_log warning $errormessage + } else { + switch -regexp $lex_status { + "^passed$" { ns_log warning "ITEM ID $id_from_ref HAS A TRACK WITH $lex_status"} + "^completed$" { ns_log warning "ITEM ID $id_from_ref HAS A TRACK WITH $lex_status" } + default { + ns_log warning "ITEM ID $id_from_ref HAS A TRACK WITH $lex_status" + append errormessage "$lex_status : $id_from_ref_title ($id_from_ref)" + append errormessage "
" + ns_log warning $errormessage + } + } + } + #if found session for id_from_ref + } + #if found id_from_ref + } + #foreach close + + if { [info exists errormessage] } { + ns_log warning $errormessage + append message " + + + + + +

$item_title :


+
Please first complete following items :


+" $errormessage + ns_return 200 text/html $message + ad_script_abort + } + # This is the revision of the file (html, jpg, etc) set cr_revision_id [item::get_best_revision $cr_item_id] set cr_item_mime [item::get_mime_info $cr_revision_id mime_info] - if { ![string equal -length 4 "text" $mime_info(mime_type)] } { - # It's a file. + if { ![string equal -length 4 "text" $mime_info(mime_type)] || [string equal "text/xml" $mime_info(mime_type)]} { + # It's a binary or XML file. + ns_log debug "BINARY/XML FILE FROM RECORD VIEW" + ns_log debug "lorsm - (SCORM) record-view - TEXT - it's a file. should we get an error?" cr_write_content -revision_id $cr_revision_id ad_script_abort } else { + # It's a textual/xml file. set href "$url2/$href" regsub -all {//} $href {/} href set ims_item_id $cr_revision_id # lorsm::set_content_root content_root lorsm::set_ims_item_id $item_id + ns_log debug "SCORM record-view : TEXT - $href cr_item_id $cr_item_id item_id $item_id ims_item_id $ims_item_id revision_id $revision_id " + + ad_set_client_property lorsm ims_id $item_id + #ad_set_client_property lorsm ims_id $revision_id + # we use nsv variables to set the delivery environment this is a # temporary solution until we find something a bit better if {[nsv_exists delivery_vars [ad_conn session_id]]} { nsv_unset delivery_vars [ad_conn session_id] } - nsv_set delivery_vars [ad_conn session_id] [list] + #the delivery environment is passed to view/index.vuh which fetches + #everything from content repository + nsv_set delivery_vars [ad_conn session_id] [list] nsv_lappend delivery_vars [ad_conn session_id] $content_root - ad_returnredirect [export_vars -base view/$href {ims_item_id man_id} ] + nsv_lappend delivery_vars [ad_conn session_id] $item_id + + ad_returnredirect [export_vars -base view/$href {ims_item_id} ] ad_script_abort } } else { lorsm::set_ims_item_id $item_id + ns_log debug "lorsm - (SCORM) record-view - EMPTY CR_ITEM_ID - cr_item_id $cr_item_id item_id $item_id" + ad_set_client_property lorsm ims_id $item_id + # We have no content, so wipe item_id from the lorsm namespace # This fixes a strange bug if you click a 'no content' menu item # repeatedly and different content appears! + if { [info exists lorsm::item_id] } { set lorsm::item_id "" } - set delivery_format [db_string get_format "select folder_name from lorsm_course_presentation_formats f, ims_cp_manifests m where f.format_id=m.course_presentation_format and m.man_id=:man_id"] - if {$delivery_format eq "delivery-progress-bar"} { - rp_form_put __include /packages/lorsm/lib/default - rp_internal_redirect /packages/lorsm/www/delivery/delivery-progress-bar - ad_script_abort - } rp_internal_redirect -absolute_path [acs_root_dir]/templates/lorsm-default - } - } } \ No newline at end of file Index: openacs-4/packages/lorsm/www/delivery/scorm.css =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/scorm.css,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/lorsm/www/delivery/scorm.css 7 Jun 2006 14:05:44 -0000 1.2 +++ openacs-4/packages/lorsm/www/delivery/scorm.css 13 Aug 2007 09:20:16 -0000 1.3 @@ -1,19 +1,19 @@ /* body {background: url(/dotlrn/resources/00_sfondo.gif) repeat-x top;} */ body {background-color: #000; } - a { font-family: Helvetica,Arial; +a { font-family: Helvetica,Arial; font-weight: bold; font-size: 0.7em; color: #FFFFFF; - white-space:normal; - } + white-space:normal; +} - a.current a:active { font-family: Helvetica,Arial; +a.current a:active { font-family: Helvetica,Arial; font-weight: bold; font-size: 0.7em; color: #FFFF00; white-space:normal; - } +} a.two { color: #6A6; } a.one { color: #fff; } @@ -39,8 +39,29 @@ border: 3px inset #00b; } +h1, h2, h3, h4, h5, h6 { + font-family: Helvetica,Arial; + font-weight: bold; + color: #fff; + white-space:normal; +} +.organization_class { + font-family: Helvetica,Arial; + font-weight: bold; + font-size: 12px; + color: #fff; + white-space:normal; +} +.usermessage_class { + font-family: Helvetica,Arial; + font-weight: bold; + font-size: 0.7em; + white-space:normal; + color: red; +} + /* a.button { font: 65% arial; border: solid 1px black; Index: openacs-4/packages/lorsm/www/delivery/servlet.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/servlet.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/lorsm/www/delivery/servlet.tcl 15 May 2007 20:14:46 -0000 1.3 +++ openacs-4/packages/lorsm/www/delivery/servlet.tcl 13 Aug 2007 09:20:16 -0000 1.4 @@ -13,8 +13,12 @@ } -errors { } -#set the following accordingly to Debug, Warning or Notice -set level "Debug" +#set the following accordingly to debug or Notice +set basiclevel "debug" +set tracelevel "debug" +#tracelevel debug will show messages only at debug level +#tracelevel Notice will show all messages. same goes for basiclevel +#see index.tcl for setting java/javascript debugging by setting debuglevel #try to circumvent browsers caching strategies set s [ns_set new] @@ -27,58 +31,100 @@ set user_id [ad_conn user_id] acs_user::get -user_id $user_id -array user set username $user(username) +ns_log $tracelevel "---------------------------------------" +ns_log $basiclevel " LMS Rte server START" +ns_log $tracelevel "---------------------------------------" +ns_log $tracelevel "username: $username" set currentcourse [ad_get_client_property lorsm currentcourse] +ns_log $tracelevel "man_id: $currentcourse" #this is not used in this proc, so far set currentpage [ad_get_client_property lorsm ims_id] -# currentcourse is the package, currentpage is the item -# this is not working consistently set whichpage [lorsm::get_ims_item_id] -ns_log Notice "delivery-scorm::servlet username $username , currentcourse $currentcourse , currentpage $currentpage" +set initedonpage [ad_get_client_property lorsm initedonpage] +ns_log $basiclevel "lorsm ims_item_id $currentpage" +ns_log $basiclevel "lorsm initedonpage $initedonpage" + if { ! ($currentpage>0) } { - ns_log warning "lorsm - ERROR SESSION lorsm ims_id returned is $currentpage" - set currentpage 0 + ns_log $basiclevel "SCORM missing ims_item_id : $currentpage" } -ns_log $level "lorsm - currentpage $currentpage " -ns_log $level "lorsm - beginning transaction for user: $user_id course: $currentcourse page (ims_item_id): $currentpage" +set community_id [dotlrn_community::get_community_id] +ns_log $basiclevel "SCORM user: $user_id course: $currentcourse ims_item_id: $currentpage community_id: $community_id" + if { $user_id == 0 } { - #_return 303 text/plain "101" - ns_return 504 text/plain "Error=101,ErrorDescription=\"Not logged in\"" + #http 401 is unauthorized + ns_return 401 text/plain "Error=101,ErrorDescription=\"Not logged in\"" } if { $currentcourse == "" } { - ns_return 504 text/plain "Error=102,ErrorDescription=\"No current course (how did you get here?)\"" + #http 303 is error: but the answer should be found elsewhere + ns_return 303 text/plain "Error=102,ErrorDescription=\"No current course (how did you get here?)\"" } if { ! [info exists functionCalled] } { - ns_return 504 text/plain "Error=104,ErrorDescription=\"No function specified\"" + #http 400 BAD request: returned as well as when functionCalled is nonsense (see end of switch) + ns_return 400 text/plain "Error=104,ErrorDescription=\"No function specified\"" } set currenttrackid [ad_get_client_property lorsm currenttrackid] set lorsmstudenttrack [ad_get_client_property lorsm studenttrack] -set community_id [dotlrn_community::get_community_id] set package_id [ad_conn package_id] -ns_log $level "Applet beginning with parameters current: $currenttrackid lorsm - $lorsmstudenttrack community: $community_id" +ns_log $basiclevel "SCORM $functionCalled " +ns_log $basiclevel "SCORM tracking (client properties): currenttrackid: $currenttrackid lorsmtrack: $lorsmstudenttrack " ad_get_user_info set name $last_name #seems ADL wants a comma between lastname and christian append name ", " append name $first_names +if { $initedonpage != $currentpage } { + if { $functionCalled != "cmigetcat" } { + if { $functionCalled != "keepalive" } { + ns_log warning "SCORM jumping to different courses WITHOUT init!!!" + } else { + ns_log warning "SCORM keepalive still alive after LMSFinish" + } + #c'e' stato un cambiamento di item + set lorsmstudenttrack "" + ad_set_client_property lorsm initedonpage $currentpage + } +} + switch -regexp $functionCalled { null - + keepalive + { + ns_return 200 text/plain "OK" + ns_log warning "SCORM Keepalive" + } cmigetcat { - ns_log $level "lorsm - serving LMSInitialize from applet" + ns_log $tracelevel "---------------------------------------" + ns_log $basiclevel " LMSInitialise " + ns_log $tracelevel "---------------------------------------" + + if { $initedonpage != $currentpage } { + #c'e' stato un cambiamento di item + set lorsmstudenttrack "" + ad_set_client_property lorsm initedonpage $currentpage + } + if { $lorsmstudenttrack == 0 || $lorsmstudenttrack == "" } { - ns_log $level "lorsm - called with no track id for current session (istrackable is off): try to fetch one" + ns_log $basiclevel "SCORM : lorsm student new track " #here track id was not set (course is not lors-trackable) #we should first try to see if we find an already open track in lorsm.track + set lorsmstudenttrack [lorsm::track::new \ + -user_id $user_id \ + -community_id $community_id \ + -course_id $currentcourse] + ad_set_client_property lorsm studenttrack $lorsmstudenttrack + ns_log $basiclevel "SCORM tracking has in any case created a lorsm_student_tracking track_id: $lorsmstudenttrack" if { ! [ db_0or1row isanysuspendedsession " - select lorsm.track_id as track_id from lorsm_student_track lorsm, lorsm_cmi_core cmi + select lorsm.track_id as track_id from + lorsm_student_track lorsm, lorsm_cmi_core cmi where lorsm.user_id = $user_id and @@ -88,41 +134,32 @@ and lorsm.track_id = cmi.track_id and - not ( - cmi.lesson_status = 'completed' - or - cmi.lesson_status = 'passed' - ) - and cmi.man_id = $currentcourse and cmi.item_id = $currentpage order by lorsm.track_id desc limit 1 " ] } { #faccio un nuovo trackid + #and + # not ( + # cmi.lesson_status = 'completed' + # or + # cmi.lesson_status = 'passed' + # ) #we create a new track which is going to be the new 'master track' for this cmi data set - set currenttrackid [lorsm::track::new \ - -user_id $user_id \ - -community_id $community_id \ - -course_id $currentcourse] - ad_set_client_property lorsm studenttrack $currenttrackid - ns_log $level "lorsm - Tracking has generated a lorsm_student_track new track id: $currenttrackid" + set currenttrackid $lorsmstudenttrack + ns_log $basiclevel "SCORM new track id: $currenttrackid" } else { - ns_log $level "lorsm - Tracking has not found a lorsm_cmi_core track with a non completed nor passed session." set currenttrackid $track_id - set lorsmstudenttrack [lorsm::track::new \ - -user_id $user_id \ - -community_id $community_id \ - -course_id $currentcourse] - ns_log $level "lorsm - Tracking has in any case created a lorsm_student_tracking track_id: $lorsmstudenttrack" - ad_set_client_property lorsm studenttrack $lorsmstudenttrack + ns_log $basiclevel "SCORM found a lorsm_cmi_core track with a non completed nor passed session." } } else { - ns_log $level "lorsm - called with track id for current session (=$lorsmstudenttrack) (istrackable is on): going to check whether to create a lorsm_cmi_core new track" + ns_log $basiclevel "SCORM already has current session (=$lorsmstudenttrack) (istrackable is on): going to check if the session is ok for current item" #now we look for the existance of a lorsm.cmi.core track id for this user / course / class which is still not completed if { ! [ db_0or1row isanysuspendedsession " - select lorsm.track_id as track_id from lorsm_student_track lorsm, lorsm_cmi_core cmi + select lorsm.track_id as track_id + from lorsm_student_track lorsm, lorsm_cmi_core cmi where lorsm.user_id = $user_id and @@ -132,69 +169,92 @@ and lorsm.track_id = cmi.track_id and - not ( - cmi.lesson_status = 'completed' - or - cmi.lesson_status = 'passed' - ) - and cmi.man_id = $currentcourse and cmi.item_id = $currentpage order by lorsm.track_id desc limit 1 " ] } { + #and + # not ( + # cmi.lesson_status = 'completed' + # or + # cmi.lesson_status = 'passed' + # ) + #the reasoning here is as follows: i had a $lorsmstudenttrack + #but not track for the course in lorsm_cmi_core. therefore i need to change the + #"student" track + set lorsmstudenttrack [lorsm::track::new \ + -user_id $user_id \ + -community_id $community_id \ + -course_id $currentcourse] + ad_set_client_property lorsm studenttrack $lorsmstudenttrack set currenttrackid $lorsmstudenttrack } else { set currenttrackid $track_id } } - #in any case at this stage track_id is currentely set to the value it should have in lorsm_cmi_core (disregarding if we have still to create it) + #at this stage currenttrackid is the value it should have in lorsm_cmi_core if { ! [ db_0or1row istherealready "select * from lorsm_cmi_core where track_id = :currenttrackid "]} { - ns_log $level "lorsm - Inserting track id in lorsm_cmi_core: value will be $currenttrackid" - ns_log $level "lorsm - I now have a track_id=$currenttrackid but i cannot find no corresponding record in lorsm_cmi_core " + ns_log $basiclevel "SCORM new RTE lorsm_cmi_core: id $currenttrackid" #get initialization data from manifest data already imported - if { [ db_0or1row get_adlcp_student_data { select datafromlms,maxtimeallowed,timelimitaction,masteryscore from ims_cp_items where ims_item_id=:currentpage; } ] } { - ns_log $level "lorsm - data for lorsm_cmi_student_data is $datafromlms, $maxtimeallowed, $timelimitaction, $masteryscore" - } else { - ns_log warning "lorsm - COULD NOT RETRIEVE DATA FROM LORSM_CMI_STUDENT_DATA from IMS_CP_ITEMS possibily ims_item_id should be $currentpage" - } - + db_0or1row get_adlcp_student_data { select datafromlms,maxtimeallowed,timelimitaction,masteryscore from ims_cp_items where ims_item_id=:currentpage; } + ns_log $basiclevel "SCORM data for lorsm_cmi_student_data is $datafromlms, $maxtimeallowed, $timelimitaction, $masteryscore" + # + # lesson_location is the bookmark. + # lesson_status is initialized to 'not attempted' # - db_dml lmsinitialize { insert into lorsm_cmi_core(track_id,man_id,item_id,student_id,student_name,lesson_location, + db_dml lmsinitialize { insert into lorsm_cmi_core(track_id,man_id,item_id,student_id,student_name, + lesson_location, lesson_status, launch_data, comments,comments_from_lms, session_time, total_time, time_stamp) - values(:currenttrackid,:currentcourse,:currentpage,:username,:name,:currentcourse, + values(:currenttrackid,:currentcourse,:currentpage,:username,:name, + '', 'not attempted', :datafromlms, - '','commenti da lors',0,0,CURRENT_TIMESTAMP) } + '','',0,0,CURRENT_TIMESTAMP) } + ns_log $basiclevel "SCORM Data inserting into lorsm_student_data $currenttrackid $username $maxtimeallowed" db_dml lmsinitialize { insert into lorsm_cmi_student_data(track_id,student_id,max_time_allowed,time_limit_action,mastery_score) values(:currenttrackid,:username,:maxtimeallowed,:timelimitaction,:masteryscore) } ad_set_client_property lorsm currenttrackid $currenttrackid - db_1row istherealready "select * from lorsm_cmi_core where track_id = :currenttrackid" + db_0or1row istherealready "select * from lorsm_cmi_core where track_id = :currenttrackid" #AURALOG HACK #adjust on a per-server basis - if { $currentcourse == 11287 } { - set student_id "testscorm711" - } +#if { $currentcourse == 6280 } { +#set student_id "testscorm727" +#} set returndata "cmi.core.student_id=$student_id,cmi.core.student_name=$name," append returndata "cmi.core.lesson_status=$lesson_status,cmi.core.credit=credit,cmi.core.entry=ab-initio," append returndata "cmi.core.lesson_mode=normal," append returndata "cmi.student_preference.language=italian,cmi.comments=$comments,cmi.comments_from_lms=$comments_from_lms" append returndata ",cmi.suspend_data=$suspend_data,cmi.launch_data=$launch_data" - append returndata ",cmi.student_data.max_time_allowed=$maxtimeallowed,cmi.student_data.time_limit_action=$timelimitaction" + append returndata ",cmi.student_data.max_time_allowed=$maxtimeallowed,cmi.student_data.timelimitaction=$timelimitaction" append returndata ",cmi.student_data.mastery_score=$masteryscore" } else { + ns_log $basiclevel "SCORM found RTE lorsm_cmi_core: id $currenttrackid" ad_set_client_property lorsm currenttrackid $currenttrackid #retrieve data other than core - db_0or1row get_adlcp_student_data { select max_time_allowed,time_limit_action,mastery_score from lorsm_cmi_student_data where track_id=:currenttrackid; } - # - ns_log $level "lorsm - retrieved track id in lorsm_cmi_core: $currenttrackid" + if { ! [db_0or1row get_adlcp_student_data " select max_time_allowed ,time_limit_action ,mastery_score from lorsm_cmi_student_data where track_id=:currenttrackid "] } { + ns_log Error "SCORM recoverying of student data: not successfull on $currenttrackid -> please check" + set max_time_allowed "" + set time_limit_action "" + set mastery_score "" + } else { + ns_log debug "SCORM recoverying of student data: successfull" + } + # THIS CHECK is somehow just a previous bug catcher, shouldn't actually be needed + # if { [db_resultrows] == 1 } { + # ns_log debug "SCORM recoverying of student data: successfull" + # } else { + # ns_log Error "SCORM recoverying of student data: not successfull on $currenttrackid -> please check" + # } + + ns_log $basiclevel "SCORM retrieved track id in lorsm_cmi_core: $currenttrackid" # summing up session time to total_time set total_time [expr $total_time + $session_time] set total_time_ms [expr $total_time_ms + $session_time_ms] @@ -206,27 +266,30 @@ # erasing session time from server and updating current total time set todo "UPDATE lorsm_cmi_core SET total_time = '$total_time" append todo "', total_time_ms ='$total_time_ms' " - append todo " WHERE track_id=:currenttrackid" + #append todo " WHERE track_id=:currenttrackid" + append todo " WHERE track_id=$currenttrackid" db_dml todo $todo if { [db_resultrows] == 1 } { - #ns_log $level "lorsm - time processing UPDATE: '$todo' successfull" + ns_log debug "SCORM time processing UPDATE: '$todo' successfull" } else { - ns_log Warning "lorsm - time processing UPDATE: '$todo' not successfull -> please check" + ns_log Warning "SCORM time processing UPDATE: '$todo' not successfull -> please check" } set todo "UPDATE lorsm_cmi_core SET session_time = '0" append todo "', session_time_ms ='0' " - append todo " WHERE track_id=:currenttrackid" + #append todo " WHERE track_id=:currenttrackid" + append todo " WHERE track_id=$currenttrackid" db_dml todo $todo if { [db_resultrows] == 1 } { - #ns_log $level "lorsm - data processing UPDATE: '$todo' successfull" + ns_log debug "SCORM data processing UPDATE: '$todo' successfull" } else { - ns_log Warning "lorsm - time processing UPDATE: '$todo' not successfull -> please check" + ns_log Warning "SCORM time processing UPDATE: '$todo' not successfull -> please check" } #AURALOG HACK #adjust on a per-server basis - if { $currentcourse == 11287 } { - set student_id "testscorm711" - } + #if { $currentcourse == 6280 } { + # set student_id "testscorm727" + #} + set returndata "cmi.core.student_id=$student_id,cmi.core.student_name=$name," append returndata "cmi.core.credit=$credit,cmi.core.lesson_status=$lesson_status,cmi.core.entry=$entry," append returndata "cmi.core.lesson_mode=normal,cmi.core.lesson_location=$lesson_location," @@ -235,40 +298,47 @@ append returndata ",cmi.student_data.max_time_allowed=$max_time_allowed,cmi.student_data.time_limit_action=$time_limit_action" append returndata ",cmi.student_data.mastery_score=$mastery_score" } - # AURALOG HACK - #treating time from table back to system (lorsm.cmi.time fields are showing just seconds) set prefix "0" set hours [expr int ($session_time/3600) ] set minutes [expr int (($session_time - (3600*$hours)) / 60) ] set seconds [expr int (($session_time - (3600*$hours)-$minutes*60)) ] + if { [ string length $session_time_ms] == 1 } { set session_time_ms "$prefix$session_time_ms" } if { [ string length $hours ] == 1 } { set hours "$prefix$hours" } if { [ string length $minutes] == 1 } { set minutes 0$minutes } if { [ string length $seconds] == 1 } { set seconds 0$seconds} - #set session_time "$hours:$minutes:$seconds.00" - set session_time "$hours:$minutes:$seconds" - if { ! [empty_string_p $session_time_ms] } { append session_time ".$session_time_ms" } + set session_time "$hours:$minutes:$seconds.$session_time_ms" + #if { ! [empty_string_p $session_time_ms] } { append session_time ".$session_time_ms" } set hours [expr int ($total_time/3600) ] set minutes [expr int (($total_time - (3600*$hours)) / 60) ] set seconds [expr int (($total_time - (3600*$hours)-$minutes*60)) ] + if { [ string length $total_time_ms] == 1 } { set total_time_ms "$prefix$total_time_ms" } if { [ string length $hours ] == 1 } { set hours "$prefix$hours" } if { [ string length $minutes] == 1 } { set minutes 0$minutes } if { [ string length $seconds] == 1 } { set seconds 0$seconds} - #set total_time "$hours:$minutes:$seconds.00" - set total_time "$hours:$minutes:$seconds" - if { ! [empty_string_p $total_time_ms] } { append total_time ".$total_time_ms" } + set total_time "$hours:$minutes:$seconds.$total_time_ms" + #if { ! [empty_string_p $total_time_ms] } { append total_time ".$total_time_ms" } #appending time fields to return string append returndata ",cmi.core.session_time=$session_time,cmi.core.total_time=$total_time" - ns_log $level "lorsm - passing data back to applet : $returndata" + ns_log $basiclevel "SCORM initialised, sending data to applet" + ns_log $tracelevel "$returndata" ns_return 200 text/plain "$returndata" } cmiputcat* { - ns_log $level "lorsm - serving LMSCOMMIT or LMSFINISH from applet" - ns_log $level "lorsm - received data $data from applet: processing. Reference cmi track is $currenttrackid, while lorsmstudenttrack is: $lorsmstudenttrack" + ns_log $tracelevel "---------------------------------------" + switch $functionCalled { + cmiputcat { + ns_log $basiclevel " LMSCommit" } + cmiputcatONFINISH { + ns_log $basiclevel " LMSFinish" } + } + ns_log $tracelevel "---------------------------------------" + ns_log $tracelevel "received data $data from applet: processing. " + ns_log $tracelevel "Reference cmi track is $currenttrackid, while lorsmstudenttrack is: $lorsmstudenttrack" set preparselist [lrange [ split $data "," ] 1 end] set lista [list] set value "" @@ -277,50 +347,45 @@ if { [ regexp ^cmi\.* $couple ] } { if { ! [empty_string_p $value] } { set value [concat [lindex $lista end],$value] - ns_log $level "lorsm - PARSER ending recomposing $value " + ns_log debug "SCORM PARSER ending recomposing $value " set lista [lreplace $lista end end $value] set value "" } else { - ns_log $level "lorsm - PARSER full couple $couple " + ns_log debug "SCORM PARSER full couple $couple " lappend lista $couple } } else { - ns_log $level "lorsm - PARSER partial couple $couple " + ns_log debug "SCORM PARSER partial couple $couple " set value [concat $value,$couple] - ns_log $level "lorsm - PARSER partial couple $couple " + ns_log debug "SCORM PARSER partial couple $couple " } } if { ! [empty_string_p $value] } { set value [concat [lindex $lista end],$value] - ns_log $level "lorsm - PARSER ending recomposing $value " + ns_log debug "SCORM PARSER ending recomposing $value " set lista [lreplace $lista end end $value] set value "" } - #end splitting + #end splitting list from applet foreach couple $lista { set all "" set request "" set value "" #create list named item to contain request and value regexp \(\[^=\]+\)=\(\.*\)$ $couple all request value - #set request "cmi.$request" - ns_log $level "lorsm - request from applet is $all that is $request to $value" - #set request [lindex $item 0] - #set value [lindex $item 1] + ns_log debug "SCORM request from applet is $all that is $request to $value" if { [ string length $value ] == 0 } { - ns_log Warning "lorsm - EMPTY settings : '$request' received and empty -> treating this applet anyway" + ns_log debug "SCORM EMPTY settings : '$request' received and empty -> won't skip" } - #else { set table [lindex [split $request .] 1] set column [string trim [lindex [split $request .] 2]] switch $table { null - - "" { - ns_log Warning "lorsm - EMPTY TABLENAME : '$table', '$column' not implemented -> not treating this applet request" - } + "" { ns_log debug "SCORM EMPTY TABLENAME : '$table', '$column' not implemented -> not treating this applet request" } core { if { [ string compare "total_time" $column ] } { - # time fields get a separate treatment + # string compare returns 0 for equal, -1 or +1 in other cases + # time fields preprocessing if { [ string first "time" $column ] >0 } { # conversion of HHHH:MM:SS.SS # removing leading zeros: @@ -329,40 +394,57 @@ regsub {^0} [lindex [split $value :] 1] "" minutes regsub {^0} [lindex [split $value :] 2] "" seconds regsub {^0} [lindex [split $value .] 1] "" msecs - if { [empty_string_p $msecs] } { - set msecs 0 - } + if { [empty_string_p $hours] } { set hours 0 } + if { [empty_string_p $minutes] } { set minutes 0 } + if { [empty_string_p $seconds] } { set seconds 0 } + if { [empty_string_p $msecs] } { set msecs 0 } set column_ms $column append column_ms "_ms" set todo "UPDATE lorsm_cmi_$table SET $column_ms = '" append todo $msecs - append todo "' WHERE track_id=:currenttrackid" + append todo "' WHERE track_id=$currenttrackid" + #append todo "' WHERE track_id=:currenttrackid" db_dml todo $todo if { [db_resultrows] == 1 } { - ns_log $level "lorsm - data msecs processing UPDATE: '$todo' successfull" + ns_log debug "SCORM data msecs processing UPDATE: '$todo' successfull" } else { - ns_log Warning "lorsm - data msecs processing UPDATE: '$todo' not successfull -> please check" + ns_log Warning "SCORM data msecs processing UPDATE: '$todo' not successfull -> please check" } #set minutes [string trim [lindex [split $value :] 1]] #set seconds [string trim [lindex [split $value :] 2]] set value [expr int (( $hours*60 + $minutes ) * 60 + $seconds) ] } + set todo "UPDATE lorsm_cmi_$table SET $column = '" append todo $value - append todo "' WHERE track_id=:currenttrackid" + append todo "' WHERE track_id=$currenttrackid" + #append todo "' WHERE track_id=:currenttrackid" db_dml todo $todo if { [db_resultrows] == 1 } { - ns_log $level "lorsm - data processing UPDATE: '$todo' successfull" + ns_log debug "SCORM data processing UPDATE: '$todo' successfull" } else { - ns_log Warning "lorsm - data processing UPDATE: '$todo' not successfull -> please check" + ns_log Warning "SCORM data processing UPDATE: '$todo' not successfull -> please check" + } + + #lesson_status postprocessing + if { ! [ string compare "lesson_status" $column ] } { + ns_log notice "LESSON STATUS set to $value, cascading down the tree" + #lesson status can be: + #Passed + #Completed + #Browsed + #Failed + #Not attempted + #Incomplete + ns_log debug "SCORM servlet: lesson_status postprocessing" + lorsm::delivery::scorm::check_parents -ims_item_id $currentpage } } } default { - ns_log Warning "lorsm - table: '$table', '$column' not implemented -> not treating this applet request" + ns_log Warning "SCORM table: '$table', '$column' not implemented -> not treating this applet request" } } - #} this was the if for empty value setting requests } switch $functionCalled { cmiputcat { @@ -372,25 +454,29 @@ lorsm::track::exit -track_id $currenttrackid } else { #speficic for courses for which istrackable is on lorsm::track::exit -track_id $lorsmstudenttrack } - ns_log $level "lorsm - post LMSCommit (trackid=$currenttrackid)" ns_return 200 text/plain "OK" + ns_log $basiclevel "SCORM post LMSCommit (trackid=$currenttrackid)" } cmiputcatONFINISH { set lorsmstudenttrack [ad_get_client_property lorsm studenttrack] ad_set_client_property lorsm studenttrack "" ad_set_client_property lorsm currenttrackid "" + ad_set_client_property lorsm initedonpage "" if { $lorsmstudenttrack == "" || $lorsmstudenttrack == 0 } { lorsm::track::exit -track_id $currenttrackid } else { #speficic for courses for which istrackable is on lorsm::track::exit -track_id $lorsmstudenttrack } ns_return 200 text/plain "OK" - ns_log $level "lorsm - post LMSFinish (trackid=$currenttrackid) sent ok to applet" + ns_log $basiclevel "SCORM post LMSFinish (trackid=$currenttrackid) sent ok to applet" } } } default { - ns_return 504 text/plain "Error=103,ErrorDescription=\"No functionCalled meaningful value provided\"" + #returning a BAD REQUEST and not a GATEWAY ERROR !!! + ns_return 400 text/plain "Error=103,ErrorDescription=\"No functionCalled meaningful value provided\"" } } -ns_log $level "lorsm - RTE process ending" +ns_log $tracelevel "---------------------------------------" +ns_log $basiclevel " LMS Rte server END" +ns_log $tracelevel "---------------------------------------" Index: openacs-4/packages/lorsm/www/delivery/stuff.jar =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/stuff.jar,v diff -u -N -r1.2 -r1.3 Binary files differ Index: openacs-4/packages/lorsm/www/delivery/view/index.vuh =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/delivery/view/index.vuh,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/lorsm/www/delivery/view/index.vuh 7 Jun 2006 14:05:45 -0000 1.3 +++ openacs-4/packages/lorsm/www/delivery/view/index.vuh 13 Aug 2007 09:20:16 -0000 1.4 @@ -40,6 +40,8 @@ set template_root [db_string template_root ""] +ns_log debug "view/index.vuh serving the url : $the_url with template root: $template_root" + # Serve the page # DRB: Note that content::init modifies the local variable the_root, which is treated # as though it's been passed by reference. This requires that the redirect treat the @@ -71,10 +73,12 @@ cr_write_content -revision_id $revision_id } else { # Write the ims_item_id that we recieve on the page since this is the one that holds the content - cr_write_content -revision_id $ims_item_id + ns_log warning "We have no CONTENT for this url: $the_url " + #cr_write_content -revision_id $ims_item_id } -ad_script_abort +#ad_script_abort + if { [lorsm::init the_url the_root $content_root $template_root public "" $content_type] } { # we introduced our own template rp_internal_redirect -absolute_path [acs_root_dir]/templates/lorsm-default Index: openacs-4/packages/lorsm/www/resources/lorsm-portlet.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/lorsm-portlet.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lorsm/www/resources/lorsm-portlet.js 13 Aug 2007 09:20:16 -0000 1.2 @@ -0,0 +1,48 @@ + + +function popitup(url,name) { + if (!newwindow.closed && newwindow.location) { + newwindow.location.href = url; + } + else { + newwindow=window.open(url,name,'height=200,width=150'); + if (!newwindow.opener) newwindow.opener = self; + } + if (window.focus) {newwindow.focus()} + if (!newwindow.focus) {newwindow.focus()} + + return false; +} + + +function popupnr(mylink, windowname, refocus) +{ +var mywin, href, url, options; +windowname='LRN_delivery_window'; +//alert(typeof(mylink)); +if (typeof(mylink) == 'string') + href=mylink+''; +else + href=mylink.href+''; + +options='location=no,status=no,toolbar=no,top,width=400,height=200,scrollbars=yes'; +mywin = window.open(href, windowname, options); + +try { url=mywin.document.URL; + } catch (o) { +alert ('You need to remove popup blocker'); +} + +// if we just opened the window +if ( + mywin.closed || + (! mywin.document.URL) || + (mywin.document.URL.indexOf("about") == 0) + ) + mywin.location=href; +else if (refocus) + mywin.focus(); + +return false; + +} Index: openacs-4/packages/lorsm/www/resources/icons/flag_blue.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/flag_blue.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/flag_green.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/flag_green.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/flag_orange.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/flag_orange.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/flag_red.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/flag_red.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/flag_white.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/flag_white.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/folder.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/folder.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/folder_page.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/folder_page.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/icon_accept.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/icon_accept.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/page_lock.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/page_lock.gif,v diff -u -N -r1.1 -r1.2 Binary files differ Index: openacs-4/packages/lorsm/www/resources/icons/page_tick.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lorsm/www/resources/icons/page_tick.gif,v diff -u -N -r1.1 -r1.2 Binary files differ