-
Notifications
You must be signed in to change notification settings - Fork 0
Configuring Activities
An activity is a representation of a component of the content of a course. Activities can be very simple components, such as a label, or more complex components, such as a quiz. For Moodle, an activity represents the contents of a module. To accommodate the potentially infinite number of activities with varying amounts of data, the activity representation has been designed to be extendible.
Each activity has its own set of tables in the destination database and its own set of classes in the domain model. By default, the minimum amount of information is stored for each activity. Specifically, the name of the activity. This page describes the processes for adding new activities, and activities with sub-activities to the destination database and the domain model. It also discusses the process for adding additional data to a pre-existing activity or a new activity. See the Supported Activities page for the list of activities that are currently supported by the destination database and domain model.
To add a new simple activity, which does not have sub-activities, the following actions must be taken:
- Create a table to the destination database to hold the activity data
- Create the Activity implementation class
- Create JPA a mapping between the class and the database table
The following sub-sections discuss the details of each of the above actions using the Moodle "assign" activity as an example.
A table needs to be added to the schema for the destination database to hold the data for the new activity. See the database schema documentation for a detailed description of the table structure. The following SQL statement creates the table required to hold the data for the Moodle "assign" activity.
create table if not exists activity_moodle_assign (
id bigint primary key references activity (id) on delete restrict on update cascade,
name text not null
);
The structure of the table name is: activity_<source>_<activity name>. For a table representing a new Moodle activity, the string "assign" in the SQL statement above can be replaced with the name of the new activity. If the new activity has a different source, then the string "moodle" should be replaced with the name of the new source as well.
By default, the activity classes are created from a template by a python script. The data used by the python script to fill in the templates is kept in the file: data/activities.xml. For the Moodle "assign" activity the entry in data/activities.xml is:
<activity name="Assign" type="assign"/>
The name attribute is the name of the class, and the type attribute is the name of the Activity type. Both attributes are case sensitive. For Moodle activities the type must be the name of the Moodle module.
To generate the classes, execute the following commands:
cd src/main/python
mkdir moodle
./MoodleClassGenerator.py ../../../data/activities.xml
mv moodle/* ../java/ca/uoguelph/socs/icc/edm/domain/element/activity/moodle/
Executing these commands will re-generate all of the existing classes, as well as creating the new classes. All of the generated classes are placed in the package ca.uoguelph.socs.icc.edm.domain.element.activity.moodle.
Once the database tables and classes are created, a mapping needs to be created so that the JPA implementation can translate between the class and the database table. Since there are two databases, source and destination, there are two slightly different mappings. The mappings for the destination database are located in the file mappings-coursedb-moodle.xml, and the mappings for the source database are located in the file mappings-moodledb-moodle.xml. Both files are in the programs resources. For the Moodle "assign" activity the JPA mapping for the destination database is the following:
<entity name="Assign" class="Assign" metadata-complete="true">
<table name="activity_moodle_assign"/>
<attributes>
<basic name="name">
<column name="name"/>
</basic>
<transient name="id"/>
<transient name="subActivities"/>
</attributes>
</entity>
For the source database, the JPA mapping for the Moodle "assign" activity is:
<entity name="Assign" class="Assign" metadata-complete="true">
<table name="mdl_assign"/>
<attributes>
<id name="id">
<column name="id" nullable="false" unique="true"/>
</id>
<basic name="name">
<column name="name"/>
</basic>
<transient name="subActivities"/>
</attributes>
</entity>
The key difference between the mappings for the source and destination database is the id field. For the source database the id field is mapped, while for the destination database it is transient (ignored). Idiosyncrasies in the schema for the Moodle database require an id field to be mapped. In the destination database the "assign" activity is identified though its relationship to the ActivityReference which is mapped by the superclass.
For a new activity, the name and class attributes of the entity tag and the name attribute of the table tag need to be replaced. The name and class attributes of the entity tag should contain the name of the class which is being mapped, while the name attribute of the table tag should contain the name of the associated database table.
To add a new simple activity, with sub-activities, the following actions must be taken:
- Create tables in the destination database to hold the activity, and sub-activity data, as well as the relationship table between the log and sub-activity
- Create the Activity, SubActivity, and LogReference implementation classes
- Create JPA mappings for the Activity, SubActivity and LogReference
- Update the Matcher configuration
The procedure for adding a new activity with sub-activities is similar to the procedure for adding a new activity without sub-activities. Using the Moodle "book" activity as an example, the following subsections will discuss the details of each step.
Three tables needs to be added to the schema for the destination database to hold the data for the new activity. See the database schema documentation for a detailed description of the table structure. The following SQL statements creates the tables required to hold the data for the Moodle "book" activity.
create table if not exists activity_moodle_book (
id bigint primary key references activity (id) on delete restrict on update cascade,
name text not null
);
create table if not exists activity_moodle_book_chapter (
id bigserial primary key,
book_id bigint not null references activity_moodle_book (id) on delete restrict on update cascade,
name text not null
);
create table if not exists log_moodle_book_chapter (
log_id bigint primary key references log (id) on delete cascade on update cascade,
chapter_id bigint references activity_moodle_book_chapter (id) on delete restrict on update cascade
);
The table containing the data for the activity is the same as it would be if there were not any sub-activities. For each sub-activity, two tables must be added to the schema: one for the sub-activity data, and one for the relationship between the sub-activity and log entry. The names of the three tables have the following structure:
- Activity: activity_<source>_<activity name>
- Sub-activity: activity_<source>_<activity name>_<child-table name>
- Log: log_<source>_<activity_name>_<child-table name>
For a new Moodle activity, replace the activity and sub-activity names ("book" and "chapter" in the example above) with the names of the new activity and sub-activity. For a non-Moodle activity, the string "moodle" must be replaces with the name of the activity source.
By default, the activity, sub-activity and log reference classes are created from templates by a python script. The data used by the python script to fill in the templates is kept in the file: data/activities.xml. For the Moodle "book" activity the entry in data/activities.xml is:
<activity name="Book" type="book">
<subactivity name="BookChapter">
<log name="BookChapterLog"/>
</subactivity>
</activity>
The name attribute for all of the tags is the name of the associated class, and the type attribute is the name of the Activity type. Both attributes are case sensitive. For Moodle activities the type must be the name of the Moodle module.
To generate the classes, execute the following commands:
cd src/main/python
mkdir moodle
./MoodleClassGenerator.py ../../../data/activities.xml
mv moodle/* ../java/ca/uoguelph/socs/icc/edm/domain/element/activity/moodle/
Executing these commands will re-generate all of the existing classes, as well as creating the new classes. All of the generated classes are placed in the package ca.uoguelph.socs.icc.edm.domain.element.activity.moodle.
Once the database tables and classes are created, a set of mappings needs to be created so that the JPA implementation can translate between the classes and the database tables. Since there are two databases, source and destination, there are two slightly different mappings. The mappings for the destination database are located in the file mappings-coursedb-moodle.xml, and the mappings for the source database are located in the file mappings-moodledb-moodle.xml. Both files are in the programs resources. For the Moodle "book" activity the JPA mappings for the destination database is the following:
<entity name="Book" class="Book" metadata-complete="true">
<table name="activity_moodle_book"/>
<attributes>
<basic name="name">
<column name="name"/>
</basic>
<one-to-many name="subActivities" target-entity="BookChapter" mapped-by="parent"/>
<transient name="id"/>
</attributes>
</entity>
<entity name="BookChapter" class="BookChapter" metadata-complete="true">
<table name="activity_moodle_book_chapter"/>
<attributes>
<id name="id">
<column name="id" nullable="false" unique="true"/>
<generated-value strategy="SEQUENCE" generator="activity_moodle_book_chapter_id_seq"/>
<sequence-generator name="activity_moodle_book_chapter_id_seq" sequence-name="activity_moodle_book_chapter_id_seq" initial-value="1" allocation-size="1"/>
</id>
<basic name="name">
<column name="name"/>
</basic>
<many-to-one name="parent" target-entity="Book" optional="false">
<join-column name="book_id" referenced-column-name="id" nullable="false" updatable="false"/>
</many-to-one>
<one-to-many name="references" target-entity="BookChapterLog" mapped-by="subActivity"/>
<transient name="subActivities"/>
</attributes>
</entity>
<entity name="BookChapterLog" class="BookChapterLog" metadata-complete="true">
<table name="log_moodle_book_chapter"/>
<attributes>
<many-to-one name="subActivity" target-entity="BookChapter">
<join-column name="chapter_id" nullable="false" referenced-column-name="id"/>
</many-to-one>
</attributes>
</entity>
For the source database, the JPA mapping for the Moodle "book" activity is:
<entity name="Book" class="Book" metadata-complete="true">
<table name="mdl_book"/>
<attributes>
<id name="id">
<column name="id" nullable="false" unique="true"/>
</id>
<basic name="name">
<column name="name"/>
</basic>
<one-to-many name="subActivities" target-entity="BookChapter" mapped-by="parent"/>
</attributes>
</entity>
<entity name="BookChapter" class="BookChapter" metadata-complete="true">
<table name="mdl_book_chapters"/>
<attributes>
<id name="id">
<column name="id" nullable="false" unique="true"/>
</id>
<basic name="name">
<column name="title"/>
</basic>
<many-to-one name="parent" target-entity="Book" optional="false">
<join-column name="bookid" referenced-column-name="id" nullable="false" updatable="false"/>
</many-to-one>
<transient name="references"/>
<transient name="subActivities"/>
</attributes>
</entity>
There are two major difference between the mappings for the destination and the source databases. For the activity mapping, the id field is mapped in the sources database, but it is marked as transient (ignored) in the destination database. Idiosyncrasies in the schema for the Moodle database require an id field to be mapped for the source database. In the destination database the "book" activity is identified though its relationship to the ActivityReference which is mapped by the superclass. Since Moodle does not have a LogRefernce, it is not mapped in the source database, and the relationship to the LogReference in the sub-activity is marked as transient.
For a new activity, the name and class attributes of the entity tags and the name attribute of the table tags need to be replaced. The name and class attributes of the entity tag should contain the name of the classes which is being mapped, while the name attribute of the table tag should contain the name of the associated database table.
If the new activity is to be extracted from Moodle, then a set of matchers needs to be configured to allow the extraction program to identify log entries which refer to the new sub-activity. Moodle log entries do not explicitly refer to any sub-activities. When a log entry refers to a sub-activity Moodle stores the sub-activity id in a generic info field and indicated that the log entry is referring to a sub-activity though the action, or the URL. See the Configuring Matchers page for the details on the matcher configuration. The matcher configuration for the Moodle "book" activity is:
<matcher activity="Book" subactivity="BookChapter">
<action>add chapter</action>
<action>print chapter</action>
<action>update chapter</action>
<action>view chapter</action>
</matcher>
For the "book" activity, a small set of actions determines when a sub-activity is being referenced by the log entry. In many cases it's possible to get the list of actions which references a particular sub-activity from Moodle's log_display table.
An existing activity can be extended to contain additional data by adding additional fields to the table, class and JPA mappings. If additional classes and tables are required to hold activity data, then they should be named using the same naming convention as sub-activities. When an existing activity is extended, it should be removed from "data/activities.xml" to ensure that the extended version does not get over written the next time that a simple activity is generated. For a new activity, it is probably easiest to start by generating a simple activity, as that will create all of the required boiler plate code needed to get the activity class loaded and initialized.