The Approach and Key Terminology

The Approach and Key Terminology

One of the important facets of the archive import problem is that archives can come from learning management systems other than Sakai. This means that there is not a clear-cut mapping between resources in an archive and the tools they will inhabit in Sakai. Also, since Sakai represents a large and growing ecosystem of tools, the design for parsing archives should be decoupled from the design for pushing archive resources into the various appropriate tools.

Thus the key architectural feature of the import code is that it divides the problem into two parts: reading an archive file and extracting the pieces of content out is done by exactly one parser. Taking the content pieces and stuffing them into Sakai tools is done by multiple handlers, one handler for each Sakai tool.

Parser

A parser is a class that understands how to read an archive file and extract from it a vendor-neutral collection of content objects.

Handler

A handler takes a vendor-neutral content object and stuffs it into a particular Sakai tool. A handler belongs to one and only one Sakai tool. A handler may be called upon many times in the process of importing a single archive.

A parser is written to accommodate all the specific features of a particular archive format. For example, there is a parser for Blackboard 5.5 archives, and another parser for Blackboard 6.0 archives, because the formats are different. There is yet another parser for IMS Common Cartridge 1.0. Note that only the Common Cartridge and the original Sakai format parsers are included in the Sakai release; Other parsers are available in contrib/migration/import.

The key to decoupling the parsing from the handling is that the parser must produce a collection of vendor-neutral content objects. This means that by the time they get to the handler, they are generic, and don't have any vendor-specific formatting. This ensures that the handlers don't have to have any code in them to deal with the particulars of any single format, which in turn means that the same handlers can be used again and again for any archive format, present or future.

These generic content objects still have types which identify what kind of content they are. Some examples of these content object types are: WebLink, Assessment, Announcement, etc. Each content class must implement an interface called Importable. As a group, these content objects are referred to as importables. An object called an ImportDataSource acts as a container for the group of importables. We can ask an ImportDataSource for the categories for that archive, and ask it for the Importables that match a given list of categories.

Importable

An importable is a content object that implements the Interface org.sakaiproject.importer.api.Importable. Importables are extracted as a collection by a parser, and passed one at a time to one or more handlers to be added to Sakai.

ImportDataSource

An ImportDataSource is an object that acts as a container for the Importable objects in an archive. You can think of it as the abstract representation of some archive.

Sitting between the parsers and the handlers is the ImportService. The default implementation of the ImportService, BasicImportService, keeps a list of available parsers and a list of available handlers, both of which are Spring-injected and configurable in a components.xml file. Here is how a hypothetical client of the ImportService might use it:

ImportService example
ImportService importService = org.sakaiproject.importer.cover.ImportService.getInstance(); byte[] fileData = fileFromUpload.get(); if (importService.isValidArchive(fileData)) { ImportDataSource importDataSource = importService.parseFromFile(fileData); List lst = importDataSource.getItemCategories(); importService.doImportItems(lst, siteId); }

Here are two simple data flow diagrams illustrating the two steps of the import process:

  1. parse an archive file and get back an ImportDataSource

  2. pass a collection of importables to the handlers, which then push content into Sakai