在上一篇中,我们介绍了SLK中的验证机制。今天将继续为大家介绍作为SLK重要组成部分的查询、视图以及支持的课件类型。
SLK中设立查询与视图的目的:
定义
SLK查询(SLK Query) —— 对课程记录数据表的一个查询,包含返回的栏,要满足的条件等。
一个SLK查询由一个基础学习存储(learning store)视图开始。通过在查询结果定义中指定的查询条件对该视图进行过滤,最终决定显示在课程记录列表中的记录。最后,对于每条记录,查询定义了哪些数据将被显示在栏中,以及以什么样的格式来显示。
比如,LearnerOverdue查询会显示当前学习者所有逾期未完成的课程记录,并在课程记录列表栏中显示所属的站点,课程名称,截止日期,状态和分数。每一栏都可以指定不同的文本格式。
SLK 查询集(Query Set)—— SLK查询的一个集合,通过一段xml的形式定义在SLK配置文件中。其中指定了:
ALWP以查询集来定义哪些查询要显示在摘要列表中,以及其中哪个查询是ALWP加载时默认选中的。在ALWP规范文档中有详细的使用方式。另外,关于“查询与视图”更详细的信息也请大家参考ALWP规范。
LearningStore视图是由SLK数据库中数据的一个子集组成的虚拟表。它们通过SQL SELECT语句的形式定义在slk架构(schema.xml)中。通过它可以从多个条目中返回数据,计算值,并提供条目级安全。LearningStore视图会根据视图定义处理用户的授权,仅返回当前用户有权访问的数据。所有的视图都定义在MLC数据库的架构中。
比如,其中名为LearnerAssignmentListForLearners的 LearningStore视图将会仅返回当前用户在指派流程中作为一个学习者所对应的课程记录。而且,一些数据在被视图返回之前就处理过了。例如,最终点数仅在该课程记录已经被指导员“返回”后才会显示给该学习者。对应这种情况,LearnerAssignmentListForLearners定义中会指定当学习者的课程记录状态小于”final”时,最终点数返回null。
而SLK查询是定义在SLK配置xml文件中。用于提供一种灵活的方式来组织从一个LearningStore得到的数据。SLK查询将一个LearningStore视图进行进一步过滤并以特定格式显示特定的一些栏。
通常LearningStore视图用于从数据库中返回合适的结果集,然后通过SLK使用来定制展现。
SLK支持的内容格式如下:
这个架构是如何工作的?
当我们通过一个文档库来指派一个文档时,一个eLearning操作被调用,该文档对应的一条指派(AssignmentItem)记录被创建,对于每个学习者会创建一条课程(LearnerAssignmentItem)记录,也对应到该文档。
对于eLearning内容,当学习者开始学习时,对应该课程记录会创建一条尝试记录(AttemptItem)。对于eLearning内容中每个活动(Activity,可能有多个),当该活动结束时,会创建一条新的活动尝试记录(ActiveAttemptItem)来存储其对应的CMI数据。
对于非eLearning内容,当学习者开始学习时,LearnerAssignmentItem.NonElearningStatus写一个值。指导员在批阅已完成的学习时,可以设置一个最终点数和一个评语。整个过程并没有尝试记录或活动尝试记录的创建。所以也没有地方可以存储CMI数据。
SLK大牛们分析了使用SLK API来为非eLearing内容创建尝试记录和活动尝试记录的可能性。大致想法为:
然而这条途径走不通。对应StoredLearningSession在SLK API中有太多的逻辑了,并且它与SCOMR和Class Server内容所提供的丰富数据紧密集成在一起。他们曾经考虑过“模拟”这些数据,以便当检测到非eLearning内容时,创建一个最简化版本的pseudo-data,将其写入数据库(类似AssignmentItem.RootActivityId=0),以便可以针对非eLearning内容通过欺骗的方式来使用SLK API。但思路还是不太容易理清。
后来干脆,从CMI跟踪服务等待一个传入的调用开始,当调用过来后,该服务会直接操作数据表(AttemptItem和ActiveAttemptItem)来插入记录并关联到该非eLearning内容对应的课程记录(LearnerAssignmentItem)。如果他们不存在,将会为该指派(Assignment)新建一条PackageItem(manifest为空,PackageFormat为'Document’)和一个ActivityPackageItem。这样我们就可以利用相同的数据库架构了。实质上,我们为上面提到的内容生成了一个“SCORM 伪装”。非eLearning内容因为没有manifest,所以被限制为每个包仅一个活动。
流程图
安全性
由于非eLearning内容并不能假定就能在浏览器中运行,因此它不能像SCORM和Class Server内容一样共享安全上下文。因此我们考虑使用基于web服务的REST/POX来支持数据的上传,以使开发启用CMI数据的内容变得简单。我们不能依赖像Windows验证或WS/Security这样的安全机制来自动得到一个安全上下文。
大多数基于REST/POX的web服务使用一个共享的令牌来保证调用的安全。它的实现是通过传输一个很长的由计算机生成的令牌,而且令牌的分发是基于会话的。在SLK里已经有一个这样的基于会话的令牌了,那就是LearnerAssignmentId。不幸的是,迄今为止它是一个递增的长整型数字,非常好猜。将来会变成一个随机生成的GUID,到时就可以大大提高这种方法的安全性了。然而,这个变更现在将会被postponed,因此我们可以在不需要进行昂贵的架构变更的情况下启用该功能。
更高层的设计