Index: openacs-4/packages/lors/change.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/Attic/change.txt,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/change.txt 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,60 @@ +Change log + +06-April-2004 +* Change the item, organization and manifest functions to properly use tree_sortkey (using proper context_id as parent_ids). + +07-April-2004 +* Added a link to the items on course-structure, so one can access directly the resource. + + - Better integration with file_storage, + +* Fixed the manifest_title to get rid of path-like / so it can confuse the index.vhu +* Changed the config.tcl file to: + + ns_section ns/server/${server}/module/nssock + ns_param timeout 240 ;# increase the timeout to 4 minutes instead + ns_param maxinput 5000000 ;# increase the size of the upload files + +* If not title is provided in the we add a new one: "[No Title]" ;-) + +09-April-2004 + +* Added delivery module on /package/lorsm/www/delivery + +10-April-2004 + +* course-add-3.tcl added double support for found_file variable. If more than one file_id is coming back, we check against the actual file directory we added the file from. +* .LRNized it!! ;-) + +11-April-2004 + +* Resources aren't children of item_ids. They are children of the organizations. [I'm not so sure if this is a 100% correct, but it is better than it was before. +* Added index to lors_imscp_create.sql (following DonB advice). +* Multiplicity of resources per item. We created a new table ims_cp_items_to_resources. Each resource can have one to many items. +* Added index on ims_cp_resources (identifier). I'm not terribly convinced about this. Need to continue exploring this option. + +12-April-2004 + +* Nuked the lors::imscp::findfile function. Changed it instead for lors::findmanifest, as there's no point of searching for manifest files that aren't in the root directory +* Fixed the multiple organizations issues and relations to resources +* Resources now are manifest's children (insted of organization's) +* Tested all IMS packages and they worked like a charm ;-) Except submanifests and empty organization packages. +* Added some bits of documentation to lors-imscp-proc.tcl & lors-imsmd-proc.tcl + + + +Remaining fixes: + +Urgent: + +[FIXED!] * multiplicity of resources per item (that is critical) [11-April-2004] +[FIXED!] * Resources shouldn't necesarily be linked to organizations as they should be to manifests. They are a subchild of man_id, not org_id! We should be able to add resources without having to have organizations. [12-April-2004] + + +Important + +* tree_sortkey for submanifests (and even maybe files) +* multiple courses in .LRN portlet + +Wish list: +* metadata upload LOM XML files for each resource (manifest, file, resource, etc) Index: openacs-4/packages/lors/lors.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/lors.info,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/lors.info 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,27 @@ + + + + + Learning Object Repository Service + Learning Object Repository Services + f + t + lors + + + + 0 + + + + + Ernie Ghiglione + + + + + + + + + Index: openacs-4/packages/lors/sql/postgresql/lors-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-create.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,253 @@ +-- lors data model +-- +-- @author Ernie Ghiglione (ErnieG@mm.st) +-- @creation-date 6 Nov 2003 +-- @cvs-id $Id: lors-create.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- +-- Copyright (C) 2004 Ernie Ghiglione +-- +-- This package is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 2 of the License, or (at your option) any later +-- version. +-- +-- It is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +-- details. +-- + + +-- Create Learning Object Content Type +select content_type__create_type ( + 'learning_object', -- content_type + 'content_revision', -- supertype. + 'Learning Object', -- pretty_name + 'Learning Objects', -- pretty_plural + 'lors_objects', -- table_name + 'lo_id', -- id_column + 'lors__get_title' -- name_method +); + +-- Register attributes +-- lo_type: this could be: SCO/A, asset, etc +-- according to the scheme we use (SCORM, IMS, etc). +select content_type__create_attribute ( + 'learning_object', -- content_type + 'lo_type', -- type of learning object + 'text', -- data type + 'learning object type', -- pretty + null, -- pretty plural + null, -- sort order + 'file', -- default 'f' + 'varchar(50)' -- colum spec +); + +-- If the learning object has metadata +-- Note: on the ims-md table we will record what the metadata +-- schema that we use. ie: IMS, Dublin Core, etc +select content_type__create_attribute ( + 'learning_object', -- content_type + 'has_metadata', -- column name + 'boolean', -- data type + 'has metadata', -- pretty + null, -- pretty plural + null, -- sort order + 'f', -- default 'f' + 'boolean' -- colum spec +); + +-- Add a new LO function +create or replace function lors__new_lo( + varchar, -- cr_items.name%TYPE, + integer, -- cr_items.parent_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar -- acs_objects.creation_ip%TYPE, +) returns integer as ' -- cr_items.item_id%TYPE +declare + new_lo__title alias for $1; + new_lo__folder_id alias for $2; + new_lo__user_id alias for $3; + new_lo__creation_ip alias for $4; + v_item_id integer; +begin + + v_item_id := content_item__new ( + new_lo__title, -- name + new_lo__folder_id, -- parent_id + null, -- item_id (default) + null, -- locale (default) + now(), -- creation_date (default) + new_lo__user_id, -- creation_user + new_lo__folder_id, -- context_id + new_lo__creation_ip, -- creation_ip + ''content_item'', -- item_subtype (default) + ''learning_object'', -- content_type + null, -- title (default) + null, -- description + ''text/plain'', -- mime_type (default) + null, -- nls_language (default) + null, -- text (default) + ''file'' -- storage_type + ); + + perform acs_object__update_last_modified(new_lo__folder_id,new_lo__user_id,new_lo__creation_ip); + + return v_item_id; + +end;' language 'plpgsql'; + +-- Adds a new LO revision +create or replace function lors__new_lo_version ( + -- + -- Create a new version of a learning object + -- Wrapper for content_revision__new + -- + varchar, -- cr_revisions.title%TYPE, + varchar, -- cr_revisions.description%TYPE, + varchar, -- cr_revisions.mime_type%TYPE, + integer, -- cr_items.item_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar -- acs_objects.creation_ip%TYPE +) returns integer as ' -- cr_revisions.revision_id +declare + new_version__filename alias for $1; + new_version__description alias for $2; + new_version__mime_type alias for $3; + new_version__item_id alias for $4; + new_version__creation_user alias for $5; + new_version__creation_ip alias for $6; + v_revision_id cr_revisions.revision_id%TYPE; + v_folder_id cr_items.parent_id%TYPE; +begin + -- Create a revision + v_revision_id := content_revision__new ( + new_version__filename, -- title + new_version__description, -- description + now(), -- publish_date + new_version__mime_type, -- mime_type + null, -- nls_language + null, -- data (default) + new_version__item_id, -- item_id + null, -- revision_id + now(), -- creation_date + new_version__creation_user, -- creation_user + new_version__creation_ip -- creation_ip + ); + + -- Make live the newly created revision + perform content_item__set_live_revision(v_revision_id); + + select cr_items.parent_id + into v_folder_id + from cr_items + where cr_items.item_id = new_version__item_id; + + perform acs_object__update_last_modified(v_folder_id,new_version__creation_user,new_version__creation_ip); + + return v_revision_id; + +end;' language 'plpgsql'; + + +-- Delete a LO +create or replace function lors__delete_lo ( + integer -- cr_items.item_id%TYPE +) returns integer as ' +declare + delete_lo__lo_id alias for $1; +begin + + return content_item__delete(delete_lo__lo_id); + +end;' language 'plpgsql'; + +-- Creates a folder to store LOs +create or replace function lors__new_folder( + -- + + -- + varchar, -- cr_items.name%TYPE, + varchar, -- cr_folders.label%TYPE, + integer, -- cr_items.parent_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar -- acs_objects.creation_ip%TYPE +) returns integer as ' -- cr_folders.folder_id%TYPE +declare + new_folder__name alias for $1; + new_folder__folder_name alias for $2; + new_folder__parent_id alias for $3; + new_folder__creation_user alias for $4; + new_folder__creation_ip alias for $5; + v_folder_id cr_folders.folder_id%TYPE; +begin + + -- Create a new folder + v_folder_id := content_folder__new ( + new_folder__name, -- name + new_folder__folder_name, -- label + null, -- description + new_folder__parent_id, -- parent_id + null, -- context_id (default) + null, -- folder_id (default) + now(), -- creation_date + new_folder__creation_user, -- creation_user + new_folder__creation_ip -- creation_ip + ); + + -- register the standard content types + -- JS: Note that we need to set include_subtypes + -- JS: to true since we created a new subtype. + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_revision'', -- content_type + ''t''); -- include_subtypes (default) + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_folder'', -- content_type + ''t'' -- include_subtypes (default) + ); + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_extlink'', -- content_types + ''t'' -- include_subtypes + ); + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_symlink'', -- content_types + ''t'' -- include_subtypes + ); + + -- Give the creator admin privileges on the folder + PERFORM acs_permission__grant_permission ( + v_folder_id, -- object_id + new_folder__creation_user, -- grantee_id + ''admin'' -- privilege + ); + + return v_folder_id; + +end;' language 'plpgsql'; + +-- Deletes folder +create or replace function lors__delete_folder( + integer -- cr_folders.folder_id%TYPE +) returns integer as ' -- 0 for success +declare + delete_folder__folder_id alias for $1; +begin + return content_folder__delete( + delete_folder__folder_id -- folder_id + ); + +end;' language 'plpgsql'; + + +-- loads IMS Metadata Data Model +\i lors-imsmd-create.sql +\i lors-imscp-create.sql +\i lors-imscp-package-create.sql \ No newline at end of file Index: openacs-4/packages/lors/sql/postgresql/lors-imscp-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imscp-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-imscp-create.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,279 @@ +-- IMS Content Packaging Data Model +-- +-- @author Ernie Ghiglione (ErnieG@mm.st) +-- @creation-date 6 Jan 2004 +-- @cvs-id $Id: lors-imscp-create.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- +-- Copyright (C) 2004 Ernie Ghiglione +-- +-- This package is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 2 of the License, or (at your option) any later +-- version. +-- +-- It is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +-- details. +-- + +-- And + +-- SCORM 1.2 Specs + + +----- +-- Create the object types +----- + +create function inline_0 () +returns integer as ' +begin + + PERFORM acs_object_type__create_type ( + ''ims_manifest'', -- object_type + ''Manifest'', -- pretty_name + ''Manifests'', -- pretty_plural + ''acs_object'', -- supertype + ''imscp_manifests'', -- table_name + ''man_id'', -- id_column + null , -- name_method + ''f'', + null, + null + ); + PERFORM acs_object_type__create_type ( + ''ims_organization'', -- object_type + ''Organization'', -- pretty_name + ''Organizations'', -- pretty_plural + ''ims_manifest'', -- supertype + ''imscp_organizations'', -- table_name + ''org_id'', -- id_column + null, -- name_method + ''f'', + null, + null + ); + PERFORM acs_object_type__create_type ( + ''ims_item'', -- object_type + ''Item'', -- pretty_name + ''Items'', -- pretty_plural + ''ims_organization'', -- supertype + ''imscp_items'', -- table_name + ''item_id'', -- id_column + null, -- name_method + ''f'', + null, + null + ); + PERFORM acs_object_type__create_type ( + ''ims_resource'', -- object_type + ''Resource'', -- pretty_name + ''Resources'', -- pretty_plural + ''ims_item'', -- supertype + ''imscp_resources'', -- table_name + ''org_id'', -- id_column + null, -- name_method + ''f'', + null, + null + ); + return 0; +end;' language 'plpgsql'; + +select inline_0 (); +drop function inline_0 (); + +----- +-- Create tables +---- +-- Manifests +create table ims_cp_manifests ( + man_id integer + constraint ims_cp_man_id_fk + references acs_objects(object_id) + on delete cascade + constraint ims_cp_man_id_pk + primary key, + course_name varchar(1000), + identifier varchar(1000), + version varchar(100), + orgs_default varchar(100), + hasmetadata boolean, + -- A manifest could have multiple submanifests + parent_man_id integer, + isscorm boolean, + folder_id integer, + fs_package_id integer +); + +comment on table ims_cp_manifests is ' +This table stores all the available manifests (that could be courses) in the system. +'; + +comment on column ims_cp_manifests.course_name is ' +Manifest course name +Take into account that this might be empty if we are dealing with a manifest that is not +a course in itself (but just a piece of content) +'; + +comment on column ims_cp_manifests.identifier is ' +Manifest identifier +Identifier get from the imsmanifest.xml file. +'; + +comment on column ims_cp_manifests.parent_man_id is ' +Parent manifest. +A manifest could have submanifests. If the manifest doesnt have a parent +then we put 0 +'; + +comment on column ims_cp_manifests.folder_id is ' +folder where this manifest was imported (this is a CR_Folder) +This is not the parent folder ID that we used in the importing process but the folder we +created to import the manifest/course (under that parent folder id) +'; + +comment on column ims_cp_manifests.fs_package_id is ' +This is the package id for the file-storage instance that the folder +belongs to. +'; + +-- Organizations +create table ims_cp_organizations ( + org_id integer + constraint ims_cp_org_id_fk + references acs_objects(object_id) + on delete cascade + constraint ims_cp_org_id_pk + primary key, + man_id integer + constraint ims_cp_org_man_id_fk + references ims_cp_manifests(man_id) + on delete cascade, + identifier varchar(100), + structure varchar(100), + title varchar(1000), + hasmetadata boolean +); + +-- create index for ims_cp_organizations +create index ims_cp_organizations__man_id_idx on ims_cp_organizations (man_id); + + +-- Items +create table ims_cp_items ( + item_id integer + constraint ims_cp_items_item_id_fk + references acs_objects(object_id) + on delete cascade + constraint ims_cp_items_item_id_pk + primary key, + org_id integer + constraint ims_cp_items_org_id_fk + references ims_cp_organizations(org_id) + on delete cascade, + identifier varchar(1000), + identifierref varchar(2000), + -- isvisible 1 = Yes, 0 = No + isvisible boolean, + parameters varchar(1000), + title varchar(1000), + parent_item integer, + hasmetadata boolean, +-- SCORM extensions (based on SCORM 1.2 specs) + prerequisites_t varchar(100), + prerequisites_s varchar(200), + type varchar(1000), + maxtimeallowed varchar(1000), + timelimitaction varchar(1000), + datafromlms varchar(200), + masteryscore varchar(255) +); + +-- create index for ims_cp_items +create index ims_cp_items__org_id_idx on ims_cp_items (org_id); + +-- Resources + +create table ims_cp_resources ( + res_id integer + constraint ims_cp_resources_res_id_fk + references acs_objects(object_id) + on delete cascade + constraint ims_cp_resources_res_id_pk + primary key, + man_id integer + constraint ims_cp_resources_man_id_fk + references ims_cp_manifests(man_id) + on delete cascade, + identifier varchar(1000), + type varchar(1000), + href varchar(2000), + hasmetadata boolean, + -- SCORM specific + scorm_type varchar(1000) +); + +-- create index for ims_cp_resources +create index ims_cp_resources__man_id_idx on ims_cp_resources (man_id); + +-- An item can have reference to one of more resources +-- therefore we need a table that takes care of this multiple +-- relationship + +create table ims_cp_items_to_resources ( + item_id integer + constraint ims_cp_items_to_res_item_id_fk + references ims_cp_items(item_id) + on delete cascade, + res_id integer + constraint ims_cp_items_to_resources_fk + references ims_cp_resources(res_id) + on delete cascade, + primary key (item_id, res_id) +); + +-- create index for ims_cp_items_to_resources +create index ims_cp_items_to_resources__item_id_idx on ims_cp_items_to_resources (item_id); +create index ims_cp_items_to_resources__res_id_idx on ims_cp_items_to_resources (res_id); + +-- Resource dependencies + +create sequence ims_cp_dependencies_seq start 1; + +create table ims_cp_dependencies ( + dep_id integer + constraint ims_cp_dependencies_dep_id_pk + primary key, + res_id integer + constraint ims_cp_dependencies_res_id_fk + references ims_cp_resources(res_id) + on delete cascade, + identifierref varchar(2000) +); + +-- create index for ims_cp_dependencies +create index ims_cp_dependencies__res_id_idx on ims_cp_dependencies (res_id); + +-- Resource files + +create table ims_cp_files ( + file_id integer + constraint ims_cp_files_file_if_fk + references cr_items(item_id) + on delete cascade, + res_id integer + constraint ims_cp_file_res_id_fk + references ims_cp_resources(res_id) + on delete cascade, + pathtofile varchar(2000), + filename varchar(2000), + hasmetadata boolean, + constraint ims_cp_file_pk + primary key (file_id, res_id) +); + +-- create index for ims_cp_files +create index ims_cp_files__res_id_idx on ims_cp_files (res_id); Index: openacs-4/packages/lors/sql/postgresql/lors-imscp-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imscp-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-imscp-drop.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,23 @@ +-- IMS Content Packaging data model +-- +-- @author Ernie Ghiglione (ErnieG@ee.usyd.edu.au) +-- @creation-date 6 Jan 2004 +-- @cvs-id $Id: lors-imscp-drop.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- Based on IMS Content Packaging Specifications Version 1.1.2 +-- http://www.imsglobal.org/content/packaging/cpv1p1p2/imscp_infov1p1p2.html + +-- And + +-- SCORM 1.2 Specs + +-- Manifests +drop table ims_cp_dependencies; +drop sequence ims_cp_dependencies_seq; +drop table ims_cp_files; +drop table ims_cp_resources; +drop table ims_cp_items; +drop table ims_cp_organizations; +drop table ims_cp_manifests; + + Index: openacs-4/packages/lors/sql/postgresql/lors-imscp-package-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imscp-package-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-imscp-package-create.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,376 @@ +-- IMS Content Packaging Package +-- +-- @author Ernie Ghiglione (ErnieG@mm.st) +-- @creation-date 6 Jan 2004 +-- @cvs-id $Id: lors-imscp-package-create.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- +-- Copyright (C) 2004 Ernie Ghiglione +-- +-- This package is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 2 of the License, or (at your option) any later +-- version. +-- +-- It is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +-- details. +-- + +-- And + +-- SCORM 1.2 Specs + +create or replace function ims_manifest__new ( + integer, -- manifest_id + varchar, -- course_name + varchar, -- identifier + varchar, -- version + varchar, -- orgs_default + boolean, -- hasmetadata + integer, -- parent_man_id + boolean, -- isscorm + integer, -- folder_id + integer, -- fs_package_id + timestamp with time zone, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) +returns integer as ' +declare + p_man_id alias for $1; + p_course_name alias for $2; + p_identifier alias for $3; + p_version alias for $4; + p_orgs_default alias for $5; + p_hasmetadata alias for $6; + p_parent_man_id alias for $7; + p_isscorm alias for $8; + p_folder_id alias for $9; + p_fs_package_id alias for $10; + p_creation_date alias for $11; + p_creation_user alias for $12; + p_creation_ip alias for $13; + p_package_id alias for $14; + + v_man_id integer; +begin + v_man_id := acs_object__new ( + p_man_id, -- object_id + ''ims_manifest'', -- object_type + p_creation_date, -- creation_date + p_creation_user, -- creation_user + p_creation_ip, -- creation_ip + p_package_id, -- context_id + ''t'' -- security_inherit_p + ); + + insert into ims_cp_manifests + (man_id, course_name, identifier, version, orgs_default, hasmetadata, parent_man_id, isscorm, folder_id, fs_package_id) + values + (v_man_id, p_course_name, p_identifier, p_version, p_orgs_default, p_hasmetadata, p_parent_man_id, p_isscorm, p_folder_id, p_fs_package_id); + + return v_man_id; +end; +' language 'plpgsql'; + +create or replace function ims_manifest__delete ( + integer --manifest_id +) +returns integer as ' +declare + p_man_id alias for $1; +begin + perform acs_object__delete(p_man_id); + delete from ims_cp_manifests where man_id = p_man_id; + return 0; +end; +' language 'plpgsql'; + + +create or replace function ims_organization__new ( + integer, -- org_id + integer, -- man_id + varchar, -- identifier + varchar, -- structure + varchar, -- title + boolean, -- hasmetadata + timestamp with time zone, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) +returns integer as ' +declare + p_org_id alias for $1; + p_man_id alias for $2; + p_identifier alias for $3; + p_structure alias for $4; + p_title alias for $5; + p_hasmetadata alias for $6; + p_creation_date alias for $7; + p_creation_user alias for $8; + p_creation_ip alias for $9; + p_package_id alias for $10; + + v_org_id integer; +begin + v_org_id := acs_object__new ( + p_org_id, -- object_id + ''ims_organization'', -- object_type + p_creation_date, -- creation_date + p_creation_user, -- creation_user + p_creation_ip, -- creation_ip + p_man_id, -- context_id + ''t'' -- security_inherit_p + ); + + insert into ims_cp_organizations + (org_id, man_id, identifier, structure, title, hasmetadata) + values + (v_org_id, p_man_id, p_identifier, p_structure, p_title, p_hasmetadata); + + return v_org_id; +end; +' language 'plpgsql'; + +create or replace function ims_organization__delete ( + integer --manifest_id +) +returns integer as ' +declare + p_org_id alias for $1; +begin + perform acs_object__delete(p_org_id); + delete from ims_cp_organizations where org_id = p_org_id; + return 0; +end; +' language 'plpgsql'; + +create or replace function ims_item__new ( + integer, -- item_id + integer, -- org_id + varchar, -- identifier + varchar, -- identifierref + boolean, -- isvisible + varchar, -- parameters + varchar, -- title + integer, -- parent_item + boolean, -- hasmetadata +-- SCORM extension + varchar, -- prerequisites_t + varchar, -- prerequisites_s + varchar, -- type + varchar, -- maxtimeallowed + varchar, -- timelimitaction + varchar, -- datafromlms + varchar, -- masteryscore + timestamp with time zone, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) +returns integer as ' +declare + p_item_id alias for $1; + p_org_id alias for $2; + p_identifier alias for $3; + p_identifierref alias for $4; + p_isvisible alias for $5; + p_parameters alias for $6; + p_title alias for $7; + p_parent_item alias for $8; + p_hasmetadata alias for $9; + p_prerequisites_t alias for $10; + p_prerequisites_s alias for $11; + p_type alias for $12; + p_maxtimeallowed alias for $13; + p_timelimitaction alias for $14; + p_datafromlms alias for $15; + p_masteryscore alias for $16; + p_creation_date alias for $17; + p_creation_user alias for $18; + p_creation_ip alias for $19; + p_package_id alias for $20; + + v_item_id integer; +begin + v_item_id := acs_object__new ( + p_item_id, -- object_id + ''ims_item'', -- object_type + p_creation_date, -- creation_date + p_creation_user, -- creation_user + p_creation_ip, -- creation_ip + p_parent_item, -- context_id + ''t'' -- security_inherit_p + ); + + insert into ims_cp_items + (item_id, org_id, identifier, identifierref, isvisible, parameters, title, parent_item, hasmetadata, prerequisites_t, prerequisites_s, type, maxtimeallowed, timelimitaction, datafromlms, masteryscore) + values + (v_item_id, p_org_id, p_identifier, p_identifierref, p_isvisible, p_parameters, p_title, p_parent_item, p_hasmetadata, p_prerequisites_t, p_prerequisites_s, p_type, p_maxtimeallowed, p_timelimitaction, p_datafromlms, p_masteryscore); + + return v_item_id; +end; +' language 'plpgsql'; + + +create or replace function ims_item__delete ( + integer --manifest_id +) +returns integer as ' +declare + p_item_id alias for $1; +begin + perform acs_object__delete(p_item_id); + delete from ims_cp_items where item_id = p_item_id; + return 0; +end; +' language 'plpgsql'; + +create or replace function ims_resource__new ( + integer, -- res_id + integer, -- man_id + varchar, -- identifier + varchar, -- type + varchar, -- href + varchar, -- scorm_type + boolean, -- hasmetadata + timestamp with time zone, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) +returns integer as ' +declare + p_res_id alias for $1; + p_man_id alias for $2; + p_identifier alias for $3; + p_type alias for $4; + p_href alias for $5; + p_scorm_type alias for $6; + p_hasmetadata alias for $7; + p_creation_date alias for $8; + p_creation_user alias for $9; + p_creation_ip alias for $10; + p_package_id alias for $11; + + v_res_id integer; +begin + v_res_id := acs_object__new ( + p_res_id, -- object_id + ''ims_resource'', -- object_type + p_creation_date, -- creation_date + p_creation_user, -- creation_user + p_creation_ip, -- creation_ip + p_man_id, -- context_id + ''t'' -- security_inherit_p + ); + + insert into ims_cp_resources + (res_id, man_id, identifier, type, href, scorm_type, hasmetadata) + values + (v_res_id, p_man_id, p_identifier, p_type, p_href, p_scorm_type, p_hasmetadata); + + return v_res_id; +end; +' language 'plpgsql'; + +create or replace function ims_resource__delete ( + integer --manifest_id +) +returns integer as ' +declare + p_res_id alias for $1; +begin + perform acs_object__delete(p_res_id); + delete from ims_cp_resources where res_id = p_res_id; + return 0; +end; +' language 'plpgsql'; + +-- ims_cp_item_to_resource table + +create or replace function ims_cp_item_to_resource__new ( + integer, -- item_id + integer -- res_id +) +returns integer as ' +declare + p_item_id alias for $1; + p_res_id alias for $2; +begin + + insert into ims_cp_items_to_resources (item_id, res_id) + values + (p_item_id, p_res_id); + + return 0; +end; +' language 'plpgsql'; + +comment on function ims_cp_item_to_resource__new (integer, integer) is ' +Function to insert relationships between items and resources within a manifest.'; + +create or replace function ims_dependency__new ( + integer, -- sequence_id + integer, -- res_id + varchar -- identifierref +) +returns integer as ' +declare + p_dep_id alias for $1; + p_res_id alias for $2; + p_identifierref alias for $3; + +begin + + insert into ims_cp_dependencies (dep_id, res_id, identifierref) + values + (p_dep_id, p_res_id, p_identifierref); + + return p_dep_id; +end; +' language 'plpgsql'; + + +create or replace function ims_dependency__delete ( + integer --dep_id +) +returns integer as ' +declare + p_dep_id alias for $1; +begin + perform acs_object__delete(p_dep_id); + delete from ims_cp_dependencies where dep_id = p_dep_id; + return 0; +end; +' language 'plpgsql'; + + +create or replace function ims_file__new ( + integer, -- file_id + integer, -- res_id + varchar, -- pathtofile + varchar, -- filename + boolean -- hasmetadata +) +returns integer as ' +declare + p_file_id alias for $1; + p_res_id alias for $2; + p_pathtofile alias for $3; + p_filename alias for $4; + p_hasmetadata alias for $5; + +begin + + insert into ims_cp_files (file_id, res_id, pathtofile, filename, hasmetadata) + values + (p_file_id, p_res_id, p_pathtofile, p_filename, p_hasmetadata); + + return p_file_id; +end; +' language 'plpgsql'; \ No newline at end of file Index: openacs-4/packages/lors/sql/postgresql/lors-imsmd-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imsmd-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-imsmd-create.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,1140 @@ +-- +-- @author Ernie Ghiglione (ErnieG@mm.st) +-- @creation-date 12-NOV-2003 +-- @cvs-id $Id: lors-imsmd-create.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- +-- Copyright (C) 2004 Ernie Ghiglione +-- +-- This package is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 2 of the License, or (at your option) any later +-- version. +-- +-- It is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +-- details. +-- + +-- IMS Metadata 1.2.1 Compliant +-- http://www.imsglobal.org/metadata/imsmdv1p2p1/imsmd_infov1p2p1.html + +-- create ims metadata table +create table ims_md ( + ims_md_id integer + constraint ims_md_if_fk + references acs_objects(object_id) + on delete cascade + constraint ims_md_id_pk + primary key, + resource_type varchar(100), + schema varchar(100), + schemaversion varchar(100) +); + +-- General begins +create table ims_md_general ( + ims_md_id integer + constraint ims_md_general_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_general_ims_md_id_pk + primary key, + title_l varchar(100), + title_s varchar(1000), + structure_s varchar(1000), + structure_v varchar(1000), + agg_level_s varchar(1000), + agg_level_v varchar(1000) +); + +comment on table ims_md_general is ' +Groups information describing learning object as a whole.'; + + +comment on column ims_md_general.structure_s is ' +Underlying organizational structure of the resource +Multiplicity single value +Domain: vocabulary: {Collection, Mixed, Linear, Hierarchical, Networked, Branched, Parceled, Atomic} +Type: Vocabulary +'; + +comment on column ims_md_general.agg_level_s is ' +The functional size of the resource. +Multiplicity: single value +Type: Vocabulary +'; + +-- create a sequence for ims_md_general_title +create sequence ims_md_general_title_seq start 1; + +create table ims_md_general_title ( + ims_md_ge_ti_id integer + constraint ims_md_ge_ti_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_title_fk + references ims_md(ims_md_id) + on delete cascade, + title_l varchar(100), + title_s varchar(1000) +); + +-- create index for ims_md_general_title +create index ims_md_ge_ti__imd_md_id_idx on ims_md_general_title (ims_md_id); + +comment on table ims_md_general_title is ' +Learning objects name +Multiplicity: single valuekeywork_l +Type LangStringType (1000 char) '; + + +-- Create a sequence for ims_md-general_iden +create sequence ims_md_general_iden_seq start 1; + +create table ims_md_general_iden ( + ims_md_ge_iden_id integer + constraint ims_md_ge_iden_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_iden_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + identifier varchar(1000) +); + +-- create index for ims_md_general_iden +create index ims_md_ge_iden__imd_md_id_idx on ims_md_general_iden (ims_md_id); + +comment on table ims_md_general_iden is ' +Globally unique label for learning object. +'; + +-- to ensure better performance we create a sequence for ims_md-general_iden +create sequence ims_md_general_cata_seq start 1; + +create table ims_md_general_cata ( + ims_md_ge_cata_id integer + constraint ims_md_ge_cata_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_cata_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + catalog varchar(1000), + entry_l varchar(100), + entry_s varchar(1000) +); + +-- create index for ims_md_general_cata +create index ims_md_ge_cata__imd_md_id_idx on ims_md_general_cata (ims_md_id); + +comment on table ims_md_general_cata is ' +Describes the name of the catalog +'; + +-- sequence ims_md_general_lang_seq +create sequence ims_md_general_lang_seq start 1; + +create table ims_md_general_lang ( + ims_md_ge_lang_id integer + constraint ims_md_ge_lang_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_lang_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + language varchar(100) +); + +-- create index for ims_md_general_lang +create index ims_md_ge_lang__imd_md_id_idx on ims_md_general_lang (ims_md_id); + +comment on column ims_md_general_lang.language is ' +Learning objects language (can be Language without Country subcode; implies intended language of target audience). "None" is also acceptable. +Multiplicity: unordered list, smallest permitted maximum: 10 items; ISO 639-ISO 3166, see also xml:lang (RFC1766) +Domain: LanguageID = Langcode(-Subcode)*, with Langcode a two-letter language code as defined by ISO639 and Subcode a country code from ISO3166. +Type: String (100 char) +'; + +-- create seq for ims_md_general_desc table +create sequence ims_md_general_desc_seq start 1; + +create table ims_md_general_desc ( + ims_md_ge_desc_id integer + constraint ims_md_ge_desc_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_desc_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + descrip_l varchar(100), + descrip_s varchar(2000) +); + +-- create index for ims_md_general_desc +create index ims_md_ge_desc__imd_md_id_idx on ims_md_general_desc (ims_md_id); + +comment on column ims_md_general_desc.descrip_l is ' +Describes learning objects content. +Multiplicity: unordered list, smallest permitted maximum: 10 items +Type: LangStringType (2000 char) +'; + +-- create seq for ims_md_general_key table + +create sequence ims_md_general_key_seq start 1; + +create table ims_md_general_key ( + ims_md_ge_key_id integer + constraint ims_md_ge_key_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_key_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + keyword_l varchar(100), + keyword_s varchar(1000) +); + +-- create index for ims_md_general_key +create index ims_md_ge_key__imd_md_id_idx on ims_md_general_key (ims_md_id); + +comment on column ims_md_general_key.keyword_l is ' +Contains keyword description of the resource. +Multiplicity: unordered list, smallest permitted maximum: 10 items +Type: LangStringType (1000 char) +'; + +--create seq for ims_md_general_cover +create sequence ims_md_general_cover_seq start 1; + +create table ims_md_general_cover ( + ims_md_ge_cove_id integer + constraint ims_md_ge_cove_id_pk + primary key, + ims_md_id integer + constraint ims_md_ge_key_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + cover_l varchar(100), + cover_s varchar(1000) +); + +-- create index for ims_md_general_cover +create index ims_md_ge_cover__imd_md_id_idx on ims_md_general_cover (ims_md_id); + +comment on column ims_md_general_cover.cover_l is ' +Temporal / spatial characteristics of content (e.g., historical context). +Multiplicity: unordered list, smallest permitted maximum: 10 items +Type: LangStringType (1000 char) +'; + +-- Life Cycle begins + +create table ims_md_life_cycle ( + ims_md_id integer + constraint ims_md_life_cycle_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_life_cycle_ims_md_id_pk + primary key, + version_l varchar(100), + version_s varchar(50), + status_s varchar(1000), + status_v varchar(1000) +); + +comment on table ims_md_life_cycle is ' +History and current state of resource. +Multiplicity: single instance +'; + +comment on column ims_md_life_cycle.version_l is ' +The edition of the learning object. +Multiplicity: single value +LangStringType (50 char) +'; + +comment on column ims_md_life_cycle.status_s is ' +Learning objects editorial condition. +Multiplicity: single value +Domain: vocabulary: {Draft, Final, Revised, Unavailable} +Type: Vocabulary +'; + +-- for life cycle contributors we have to create a sequence since +-- otherwise the primary key get out of control and also the reference +-- to life cycle contributores entities is just not right + +create sequence ims_md_life_cycle_contrib_seq start 1; + +create table ims_md_life_cycle_contrib ( + ims_md_lf_cont_id integer -- from sequence + constraint ims_md_lc_cont_ims_md_lf_id_pk + primary key, + ims_md_id integer + constraint ims_md_lc_contrib_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + role_s varchar(1000), + role_v varchar(1000), + cont_date varchar(200), + cont_date_l varchar(100), + cont_date_s varchar(1000) +); + +-- create index for ims_md_life_cycle_contrib +create index ims_md_lf_cont__imd_md_id_idx on ims_md_life_cycle_contrib (ims_md_id); + +comment on table ims_md_life_cycle_contrib is ' +Persons or organizations contributing to the resource (includes creation, edits, and publication). +Multiplicity: unordered list; smallest permitted maximum items: 30 +'; + +comment on column ims_md_life_cycle_contrib.role_s is ' +Kind of contribution. +Multiplicity: single value +Domain: vocabulary: {Author, Publisher, Unknown, Initiator, Terminator, Validator, Editor, Graphical Designer, Technical Implementer, Content Provider, Technical Validator, Educational Validator, Script Writer, Instructional Designer} +Type: Vocab +'; + +comment on column ims_md_life_cycle_contrib.cont_date is ' +Date of contribution. +Multiplicity: single value +Type: DateType +'; + +-- create sequence for ims_md_life_cycle_contrib_entity table +create sequence ims_md_life_cycle_contrib_entity_seq start 1; + +create table ims_md_life_cycle_contrib_entity ( + ims_md_lf_cont_enti_id integer + constraint ims_md_lf_cont_enti_id_pk + primary key, + ims_md_lf_cont_id integer + constraint ims_md_lf_cont_ent_fk + references ims_md_life_cycle_contrib(ims_md_lf_cont_id) + on delete cascade, + entity varchar(1000) +); + +comment on table ims_md_life_cycle_contrib_entity is ' +Entity or entities involved, most relevant first. +Multiplicity: ordered list; smallest permitted maximum items: 40; vCard +Domain: vCard +Type: String (1000 chars) +'; + +-- Metadata begins + +create table ims_md_metadata ( + ims_md_id integer + constraint ims_md_metadata_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_metadata_ims_md_id_pk + primary key, + language varchar(100) +); + +comment on table ims_md_metadata is ' +Features of the description rather than the resource. +Multiplicity: single instance +'; + +comment on column ims_md_metadata.language is ' +Language of the meta-data instance. This is the default language for all LangString values. +Multiplicity: single value +Type: String (100 char) +'; + +-- create seq for ims_md_metadata_cata +create sequence ims_md_metadata_cata_seq start 1; + +create table ims_md_metadata_cata ( + ims_md_md_cata_id integer + constraint ims_md_md_cata_id_pk + primary key, + ims_md_id integer + constraint ims_md_md_cata_ims_md_id_fk + references ims_md (ims_md_id) + on delete cascade, + catalog varchar(1000), + entry_l varchar(100), + entry_s varchar(1000) +); + +-- create index for ims_md_metadata_cata +create index ims_md_md_cata__imd_md_id_idx on ims_md_metadata_cata (ims_md_id); + +comment on table ims_md_metadata_cata is ' +A unique label for the meta-data. +single value +'; + +comment on column ims_md_metadata_cata.catalog is ' +Designation given to the meta-data instance. Source of following string value. +single value +String (1000 char) +'; + +-- create seq for ims_md_metadata_contrib +create sequence ims_md_metadata_contrib_seq start 1; + +create table ims_md_metadata_contrib ( + ims_md_md_cont_id integer -- from sequence + constraint ims_md_md_cont_ims_md_md_id_pk + primary key, + ims_md_id integer + constraint ims_md_md_contrib_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + role_s varchar(1000), + role_v varchar(1000), + cont_date varchar(200), + cont_date_l varchar(100), + cont_date_s varchar(1000) +); + +-- create index for ims_md_metadata_cont +create index ims_md_md_cont__imd_md_id_idx on ims_md_metadata_contrib (ims_md_id); + +comment on table ims_md_metadata_contrib is ' +Persons or organizations contributing to the meta-data +Multiplicity: ordered list, smallest permitted maximum: 10 items +'; + +comment on column ims_md_metadata_contrib.role_s is ' +Kind of contribution. +single value +Domain: vocabulary: {Creator, Validator} +'; + +comment on column ims_md_metadata_contrib.cont_date is ' +Date of contribution. +single value +DateType +'; + +-- create sequence for ims_md_metadata_contrib_entity table +create sequence ims_md_metadata_contrib_entity_seq start 1; + +create table ims_md_metadata_contrib_entity ( + ims_md_md_cont_enti_id integer + constraint ims_md_md_cont_enti_id_pk + primary key, + ims_md_md_cont_id integer + constraint ims_md_lf_cont_ent_fk + references ims_md_metadata_contrib(ims_md_md_cont_id) + on delete cascade, + entity varchar(1000) +); + +comment on column ims_md_metadata_contrib_entity.entity is ' +Entity or entities involved, most relevant first. +Multiplicity: ordered list as vCard; smallest permitted maximum: 10 items +Domain: vCard +String (1000 char) +'; + +create table ims_md_metadata_scheme ( + ims_md_id integer + constraint ims_md_ms_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + scheme varchar(30), + constraint ims_md_md_sc_pk + primary key (ims_md_id, scheme) +); + +comment on table ims_md_metadata_scheme is ' +Names the structure of the meta-data (this includes version). +unordered list; smallest permitted maximum: 10 items +String (30 char) +'; + + +-- Technical begins + +create table ims_md_technical ( + ims_md_id integer + constraint ims_md_te_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_te_ims_md_id_pk + primary key, + t_size varchar(30), + instl_rmrks_l varchar(100), + instl_rmrks_s varchar(1000), + otr_plt_l varchar(100), + otr_plt_s varchar(1000), + duration varchar(200), + duration_l varchar(100), + duration_s varchar(1000) +); + +comment on table ims_md_technical is ' +Technical features of the learning object. +single instance +'; + +comment on column ims_md_technical.t_size is ' +The size of the digital resource in bytes. Only the digits "0" - "9" should be used; the unit is bytes, not MBytes, GB, etc. +single value +String (30 char) +'; + +comment on column ims_md_technical.instl_rmrks_l is ' +Description on how to install the resource. +single value +Type: LangStringType (1000 char) +'; + +comment on column ims_md_technical.otr_plt_l is ' +Information about other software and hardware requirements. +single value +Type: LangStringType (1000 char) +'; + +comment on column ims_md_technical.duration is ' +Time a continuous learning object takes when played at intended speed, in seconds. +Multiplicity: single value +Domain: ISO8601 +Type: DateType +'; + +-- create sequence for ims_md_technical_format table +create sequence ims_md_technical_format_seq start 1; + +create table ims_md_technical_format ( + ims_md_te_fo_id integer + constraint ims_md_te_fo_id_pk + primary key, + ims_md_id integer + constraint ims_md_te_fo_id_fk + references ims_md(ims_md_id) + on delete cascade, + format varchar(500) +); + +-- create index for ims_md_technical_format +create index ims_md_te_format__imd_md_id_idx on ims_md_technical_format (ims_md_id); + +comment on column ims_md_technical_format.format is ' +Technical data type of the resource. +Multiplicity: unordered list, smallest permitted maximum: 40 items +Domain: restricted: MIME type or "non-digital" +Type: String (500 char) +'; + +-- create sequence for ims_md_technical_location table +create sequence ims_md_technical_location_seq start 1; + +create table ims_md_technical_location ( + ims_md_te_lo_id integer + constraint ims_md_te_lo_id_pk + primary key, + ims_md_id integer + constraint ims_md_te_lo_id_fk + references ims_md(ims_md_id) + on delete cascade, + type varchar(100), + location varchar(1000) +); + +-- create index for ims_md_technical_location +create index ims_md_te_location__imd_md_id_idx on ims_md_technical_location (ims_md_id); + +comment on column ims_md_technical_location.type is ' +Values permitted: TEXT or URI +Reference where the location is +'; + +comment on column ims_md_technical_location.location is ' +A location or a method that resolves to a location of the resource. Preferable Location first. +Multiplicity: ordered list; smallest permitted maximum: 10 items +Type: String (1000 char) +'; + +-- create sequence for ims_md_technical_requirement table +create sequence ims_md_technical_requirement_seq start 1; + +create table ims_md_technical_requirement ( + ims_md_te_rq_id integer + constraint ims_md_te_rq_id_pk + primary key, + ims_md_id integer + constraint ims_md_te_rq_id_fk + references ims_md(ims_md_id) + on delete cascade, + type_s varchar(1000), + type_v varchar(1000), + name_s varchar(1000), + name_v varchar(1000), + min_version varchar(30), + max_version varchar(30) +); + +-- create index for ims_md_technical_requirement +create index ims_md_te_req__imd_md_id_idx on ims_md_technical_requirement (ims_md_id); + +comment on table ims_md_technical_requirement is ' +Needs in order to access the resource. If there are multiple requirements, then the logical connector is AND. +multiple unordered instances; smallest permitted maximum: 40 items +'; + +comment on column ims_md_technical_requirement.type_s is ' +Type of requirement. +Multiplicity: single value +Domain: vocabulary: {Operating System, Browser} +'; + +comment on column ims_md_technical_requirement.name_s is ' +Name of the required item. +Multiplicity: single value +Domain: if Type="Operating System", then vocabulary: {PC-DOS, MS- Windows, MacOS, Unix, Multi-OS, Other, None} if Type="Browser" then vocabulary: {Any, Netscape Communicator, Microsoft Internet Explorer, Opera} if other type, then open vocabulary +'; + +comment on column ims_md_technical_requirement.min_version is ' +Lowest version of the required item. +single value +String (30 char) +'; + +comment on column ims_md_technical_requirement.max_version is ' +Highest version of the required item. +single value +String (30 char) +'; + +-- Educational begins + +create table ims_md_educational ( + ims_md_id integer + constraint ims_md_ed_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_ed_ims_md_id_pk + primary key, + int_type_s varchar(1000), + int_type_v varchar(1000), + int_level_s varchar(1000), + int_level_v varchar(1000), + sem_density_s varchar(1000), + sem_density_v varchar(1000), + difficulty_s varchar(1000), + difficulty_v varchar(1000), + type_lrn_time varchar(200), + type_lrn_time_l varchar(100), + type_lrn_time_s varchar(1000) +); + +comment on table ims_md_educational is ' +Educational or pedagogic features of the learning object. +single instance +'; + +comment on column ims_md_educational.int_type_s is ' +The type of interactivity supported by the learning object. +single value +vocabulary: {Active, Expositive, Mixed, Undefined} +'; + +comment on column ims_md_educational.int_level_s is ' +Level of interactivity between an end user and the learning object. +Domain: vocabulary: {very low, low, medium, high, very high} +'; + +comment on column ims_md_educational.sem_density_s is ' +Subjective measure of the learning objects usefulness as compared to its size or duration. +Domain: vocabulary: {very low, low, medium, high, very high} +'; + +comment on column ims_md_educational.difficulty_s is ' +How hard it is to work through the learning object for the typical target audience. +single value +vocabulary: {very easy, easy, medium, difficult, very difficult} +'; + +comment on column ims_md_educational.type_lrn_time is ' +Approximate or typical time it takes to work with the resource. +single value +Domain: ISO8601 +Type: DateType +'; + + +-- create seq from ims_md_educational_lrt table +create sequence ims_md_educational_lrt_seq start 1; + +create table ims_md_educational_lrt ( + ims_md_ed_lr_id integer + constraint ims_md_ed_lr_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_lr_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + lrt_s varchar(1000), + lrt_v varchar(1000) +); + +-- create index for ims_md_educational_lrt +create index ims_md_ed_lrt__imd_md_id_idx on ims_md_educational_lrt (ims_md_id); + +comment on table ims_md_educational_lrt is ' +learningresourcetype (Specific kind of resource, most dominant kind first) +ordered list; smallest permitted maximum: 10 items +vocabulary: {Exercise, Simulation, Questionnaire, Diagram, Figure, Graph, Index, Slide, Table, Narrative Text, Exam, Experiment, ProblemStatement, SelfAssesment} +'; + +-- create seq from ims_md_educational_ieur table +create sequence ims_md_educational_ieur_seq start 1; + +create table ims_md_educational_ieur ( + ims_md_ed_ie_id integer + constraint ims_md_ed_ie_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_ie_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + ieur_s varchar(1000), + ieur_v varchar(1000) +); + +-- create index for ims_md_educational_ieur +create index ims_md_ed_ieur__imd_md_id_idx on ims_md_educational_ieur (ims_md_id); + +comment on table ims_md_educational_ieur is ' +intendedenduserrole (Normal user of the learning object, most dominant first) +Multiplicity: ordered list, smallest permitted maximum:10 items +Domain: vocabulary: {Teacher, Author, Learner, Manager} +'; + +-- create seq from ims_md_educational_context table +create sequence ims_md_educational_context_seq start 1; + +create table ims_md_educational_context ( + ims_md_ed_co_id integer + constraint ims_md_ed_co_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_co_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + context_s varchar(1000), + context_v varchar(1000) +); + +-- create index for ims_md_educational_context +create index ims_md_ed_cont__imd_md_id_idx on ims_md_educational_context (ims_md_id); + +comment on table ims_md_educational_context is ' +The typical learning environment where use of learning object is intended to take place. +Multiplicity: unordered list; smallest permitted maximum: 4 items; +Domain: vocabulary: {Primary Education, Secondary Education, Higher Education, University First Cycle, University Second Cycle, University Postgrade, Technical School First Cycle, Technical School Second Cycle, Professional Formation, Continuous Formation, Vocational Training} +'; + +-- create seq from ims_md_educational_tar table +create sequence ims_md_educational_tar_seq start 1; + +create table ims_md_educational_tar ( + ims_md_ed_ta_id integer + constraint ims_md_ed_ta_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_ta_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + tar_l varchar(100), + tar_s varchar(1000) +); + +-- create index for ims_md_educational_tar +create index ims_md_ed_tar__imd_md_id_idx on ims_md_educational_tar (ims_md_id); + +comment on table ims_md_educational_tar is ' +typicalagerange (Age of the typical intended user) +Multiplicity: unordered list; smallest permitted maximum: 5 items +'; + +-- create seq from ims_md_educational_lang table +create sequence ims_md_educational_lang_seq start 1; + +create table ims_md_educational_lang ( + ims_md_ed_la_id integer + constraint ims_md_ed_la_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_la_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + language varchar(100) +); + +-- create index for ims_md_educational_lang +create index ims_md_ed_lang__imd_md_id_idx on ims_md_educational_lang (ims_md_id); + +comment on table ims_md_educational_lang is ' +Users natural language. +smallest permitted maximum: 10 items +'; + +-- create seq from ims_md_educational_lrt table +create sequence ims_md_educational_descrip_seq start 1; + +create table ims_md_educational_descrip ( + ims_md_ed_de_id integer + constraint ims_md_ed_de_id_pk + primary key, + ims_md_id integer + constraint ims_md_ed_de_id_fk + references ims_md(ims_md_id) + on delete cascade, + descrip_l varchar(100), + descrip_s varchar(1000) +); + +-- create index for ims_md_educational_descrip +create index ims_md_ed_descrip__imd_md_id_idx on ims_md_educational_descrip (ims_md_id); + +comment on table ims_md_educational_descrip is ' +Comments on how the learning object is to be used. +single value +Type: LangStringType (1000 char) +'; + + +-- Rights begins + +create table ims_md_rights ( + ims_md_id integer + constraint ims_md_ri_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade + constraint ims_md_ri_ims_md_id_pk + primary key, + cost_s varchar(1000), + cost_v varchar(1000), + caor_s varchar(1000), + caor_v varchar(1000), + descrip_l varchar(100), + descrip_s varchar(1000) +); + +comment on table ims_md_rights is ' +Conditions of use of the resource. +single instance +'; + +comment on column ims_md_rights.cost_s is ' +Whether use of the resource requires payment. +single value +vocabulary: {yes, no} +'; + +comment on column ims_md_rights.caor_s is ' +copyrightandotherrestrictions +Whether copyright or other restrictions apply +single instance +vocabulary: {yes, no} +'; + +comment on column ims_md_rights.descrip_l is ' +Description (Comments on the conditions of use of the resource) +single value +LangStringType (1000 char) +'; + +-- Relation begins + +-- create seq for ims_md_relation table +create sequence ims_md_relation_seq start 1; + +create table ims_md_relation ( + ims_md_re_id integer + constraint ims_md_re_id_pk + primary key, + ims_md_id integer + constraint ims_md_re_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + kind_s varchar(1000), + kind_v varchar(1000) +); + +-- create index for ims_md_relation +create index ims_md_re__imd_md_id_idx on ims_md_relation (ims_md_id); + +comment on table ims_md_relation is ' +Features of the resource in relationship to other learning objects. +Multiplicity: unordered list; smallest permitted maximum: 100 items +'; + +comment on column ims_md_relation.kind_s is ' +Nature of the relationship between the resource being described and the one identified by Resource +single value +vocabulary list from Dublin Core: {IsPartOf, HasPart, IsVersionOf, HasVersion, IsFormatOf, HasFormat, References, IsReferencedBy, IsBasedOn, IsBasisFor, Requires, IsRequiredBy} +'; + +--create seq for ims_md_relation_resource table +create sequence ims_md_relation_resource_seq start 1; + +create table ims_md_relation_resource ( + ims_md_re_re_id integer + constraint ims_md_re_re_id_pk + primary key, + ims_md_re_id integer + constraint ims_md_re_re_rel_id_fk + references ims_md_relation(ims_md_re_id) + on delete cascade, + identifier varchar(1000), + descrip_l varchar(100), + descrip_s varchar(1000) +); + +-- create index for ims_md_relation_resource +create index ims_md_re_res__imd_md_re_id_idx on ims_md_relation_resource (ims_md_re_id); + +comment on table ims_md_relation_resource is ' +Resource the relationship holds for. +single instance +'; + +comment on column ims_md_relation_resource.identifier is ' +Unique Identifier of the other resource +single value +'; + +comment on column ims_md_relation_resource.descrip_l is ' +Description of the other resource. +single value +LangStringType (1000 char) +'; + +--create seq for ims_md_relation_resource_catalog table +create sequence ims_md_relation_resource_catalog_seq start 1; + +create table ims_md_relation_resource_catalog ( + ims_md_re_re_ca_id integer + constraint ims_md_re_re_ca_id_pk + primary key, + ims_md_re_re_id integer + constraint ims_md_re_re_ca_fk + references ims_md_relation_resource(ims_md_re_re_id) + on delete cascade, + catalog varchar(1000), + entry_l varchar(100), + entry_s varchar(1000) +); + +-- create index for ims_md_relation_resource_catalog +create index ims_md_re_re_cat__imd_md_re_re_id_idx on ims_md_relation_resource_catalog (ims_md_re_re_id); + +comment on table ims_md_relation_resource_catalog is ' +Description of the other resource. +unordered list; smallest permitted maximum: 10 items +'; + +comment on column ims_md_relation_resource_catalog.catalog is ' +Source of following string value +single value +String (1000 char) +'; + +comment on column ims_md_relation_resource_catalog.entry_l is ' +Actual value +single value +LangStringType (1000 char) +'; + +-- Annotation begins + +-- create seq for ims_md_annotation table +create sequence ims_md_annotation_seq start 1; + +create table ims_md_annotation ( + ims_md_an_id integer + constraint ims_md_an_id_pk + primary key, + ims_md_id integer + constraint ims_md_an_ims_md_id_fk + references ims_md(ims_md_id) + on delete cascade, + entity varchar(1000), + date varchar(200), + date_l varchar(100), + date_s varchar(1000) +); + +-- create index for ims_md_annotation +create index ims_md_an__imd_md_id_idx on ims_md_annotation (ims_md_id); + +comment on table ims_md_annotation is ' +Comments on the educational use of the learning object. +unordered list; smallest permitted maximum: 30 items +'; + +-- create seq for ims_md_annotation_descrip table +create sequence ims_md_annotation_descrip_seq start 1; + +create table ims_md_annotation_descrip ( + ims_md_an_de_id integer + constraint ims_md_an_de_id_pk + primary key, + ims_md_an_id integer + constraint ims_md_an_de_id_fk + references ims_md_annotation(ims_md_an_id) + on delete cascade, + descrip_l varchar(100), + descrip_s varchar(1000) +); + +-- create index for ims_md_annotation_descrip +create index ims_md_an_desc__imd_md_an_id_idx on ims_md_annotation_descrip (ims_md_an_id); + +comment on table ims_md_annotation_descrip is ' +Annotation descriptions. It can have descriptions in several languages +according to the langstrings. +'; + + +-- Classification begins + +-- create seq for ims_md_classification table +create sequence ims_md_classification_seq start 1; + +create table ims_md_classification ( + ims_md_cl_id integer + constraint ims_md_cl_id_pk + primary key, + ims_md_id integer + constraint ims_md_cl_id_imsmdid_fk + references ims_md(ims_md_id) + on delete cascade, + purpose_s varchar(1000), + purpose_v varchar(1000) +); + +-- create index for ims_md_annotation +create index ims_md_cl__imd_md_id_idx on ims_md_classification (ims_md_id); + +comment on table ims_md_classification is ' +Description of a characteristic of the resource by entries in classifications. +unordered list; smallest permitted maximum: 40 items +'; + +comment on column ims_md_classification.purpose_s is ' +Characteristics of the resource described by this classification entry. +single value +vocabulary: {Discipline, Idea, Prerequisite, Educational Objective, Accessibility Restrictions, Educational Level, Skill Level, Security Level} +'; + +create sequence ims_md_classification_desc_seq start 1; + +create table ims_md_classification_descrip ( + ims_md_cl_de_id integer + constraint ims_md_cl_ed_id_pk + primary key, + ims_md_cl_id integer + constraint imd_md_cl_ed_id_fk + references ims_md_classification(ims_md_cl_id) + on delete cascade, + descrip_l varchar(100), + descrip_s varchar(1000) +); + +-- create index for ims_md_classification_descrip +create index ims_md_cl_desc__imd_md_cl_id_idx on ims_md_classification_descrip (ims_md_cl_id); + +comment on table ims_md_classification_descrip is ' +A textual description of learning object relative to its stated purpose. +single value. However, it can have several langstrings +'; + +--create seq for ims_md_classification_taxpath table +create sequence ims_md_classification_taxpath_seq start 1; + +create table ims_md_classification_taxpath ( + ims_md_cl_ta_id integer + constraint ims_md_cl_ta_id_pk + primary key, + ims_md_cl_id integer + constraint ims_md_cl_ta_fk + references ims_md_classification(ims_md_cl_id) + on delete cascade, + source_l varchar(100), + source_v varchar(1000) +); + +-- create index for ims_md_classification_taxpath +create index ims_md_cl_tax__imd_md_cl_id_idx on ims_md_classification_taxpath (ims_md_cl_id); + +comment on table ims_md_classification_taxpath is ' +A taxonomic path in a specific classification. +unordered instance; smallest permitted maximum: 15 items +'; + +comment on column ims_md_classification_taxpath.source_l is ' +A specific classification. +single value +'; + +--create seq ims_md_classification_taxpath_taxon table +create sequence ims_md_classification_taxpath_taxon_seq start 1; + +create table ims_md_classification_taxpath_taxon ( + ims_md_cl_ta_ta_id integer + constraint ims_md_cl_ta_ta_id_pk + primary key, + ims_md_cl_ta_id integer + constraint ims_md_cl_ta_ta_fk + references ims_md_classification_taxpath(ims_md_cl_ta_id) + on delete cascade, + -- hierarchy is a column I inserted to show the hiearchy of the terms presented + -- ie: + -- hierarchy | taxon entry + -- 0 Information Science + -- 1 Information Processing + -- 2 Metadata + --ims_md_classification_taxpath_taxon + -- The hierarchy to be inserted by the SCORM package + hierarchy varchar(10), + identifier varchar(100), + entry_l varchar(100), + entry_s varchar(500) +); + +-- create index for ims_md_classification_taxpath_taxon +create index ims_md_cl_tax_tax__imd_md_cl_ta_id_idx on ims_md_classification_taxpath_taxon (ims_md_cl_ta_id); + +comment on table ims_md_classification_taxpath_taxon is ' +An entry in a classification. An ordered list of Taxons creates a taxonomic path, i.e. "taxonomic stairway": this is a path from a more general to more specific entry in a classification. +ordered list; smallest permitted maximum: 15 items +'; + +--create seq for ims_md_classification_keyword table +create sequence ims_md_classification_keyword_seq start 1; + +create table ims_md_classification_keyword ( + ims_md_cl_ke_id integer + constraint ims_md_cl_ke_id_pk + primary key, + ims_md_cl_id integer + constraint ims_md_cl_ke_ims_md_cl_id_fk + references ims_md_classification(ims_md_cl_id) + on delete cascade, + keyword_l varchar(100), + keyword_s varchar(1000) +); + +-- create index for ims_md_classification_keyword +create index ims_md_cl_key__imd_md_cl_id_idx on ims_md_classification_keyword (ims_md_cl_id); + +comment on table ims_md_classification_keyword is ' +Contains keyword description of learning objective relative to its stated purpose. +ordered list smallest permitted maximum: 40 items +'; Index: openacs-4/packages/lors/sql/postgresql/lors-imsmd-packages-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imsmd-packages-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/sql/postgresql/lors-imsmd-packages-create.sql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,42 @@ +-- +-- @author Ernie Ghiglione (ErnieG@mm.st) +-- @creation-date 12-NOV-2003 +-- @cvs-id $Id: lors-imsmd-packages-create.sql,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +-- +-- Copyright (C) 2004 Ernie Ghiglione +-- +-- This package is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 2 of the License, or (at your option) any later +-- version. +-- +-- It is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +-- details. +-- + +-- IMS Metadata 1.2.1 Compliant +-- http://www.imsglobal.org/metadata/imsmdv1p2p1/imsmd_infov1p2p1.html + +create or replace function ims_md_general__new (integer,varchar,varchar,varchar,varchar,varchar,varchar) +returns integer as ' +declare + p_ims_md_id alias for $1; + p_title_l alias for $5; + p_title_s alias for $6; + p_structure_s alias for $7; + p_structure_v alias for $8; + p_agg_level_s alias for $9; + p_agg_level_v alias for $10; +begin + -- inserts into + insert into ims_md_general + (ims_md_id, title_l, title_s, structure_s, structure_v, agg_level_s, agg_level_v) + values + (p_ims_md_id, p_title_l, p_title_s, p_structure_s, p_structure_v, p_agg_level_s, p_agg_level_v); + + return p_ims_md_id; + +end;' language 'plpgsql'; Index: openacs-4/packages/lors/tcl/lors-cr-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/lors-cr-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/tcl/lors-cr-procs.tcl 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,203 @@ +ad_library { + + + @creation-date 2003-10-13 + @author Ernie Ghiglione (ErnieG@mm.st) + @cvs-id $Id: lors-cr-procs.tcl,v 1.1 2004/04/22 03:42:06 ernieg Exp $ +} + +# +# Copyright (C) 2004 Ernie Ghiglione +# +# This package is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# It is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# + +namespace eval lors::cr {} + + +ad_proc -public lors::cr::has_files { + {-fs_dir:required} +} { + Checks if the fs_dir has files. If that is the case, + it returns the name of those files on a list. + Note: this does not return directories! Use has_dirs for that + + @param fs_dir File System directory +} { + set files [list] + foreach f [glob -no complain [file join $fs_dir * ]] { + set type [file type $f] + switch $type { + file { + lappend files $f + } + } + } + return $files +} + + +ad_proc -public lors::cr::has_dirs { + {-fs_dir:required} +} { + Checks if the fs_dir has directories. If that is the case, + it returns the name of those dirs on a list. + Note: this does not return file names! Use has_files for that + + @param fs_dir File System directory +} { + set directories [list] + foreach dir [glob -no complain [file join $fs_dir * ]] { + set type [file type $dir] + switch $type { + directory { + lappend directories $dir + } + } + } + return $directories +} + + +ad_proc -public lors::cr::add_folder { + {-folder_name:required} + {-parent_id:required} + {-strip_prefix {}} +} { + Adds the folder to the CR + + @param folder_name Name of the folder + @param parent_id Parent ID Folder where the folder will be created + @param strip_prefix The prefix to remove from the filename (for expanded archives) +} { + # pre-processing + + # strips the prefix + if {![empty_string_p $strip_prefix]} { + regsub "^$strip_prefix" $folder_name {} folder_name + } + + # gets the user_id and IP + set user_id [ad_conn user_id] + set creation_ip [ad_conn peeraddr] + + # strips out spaces from the name + regsub -all { +} $folder_name {_} name +# regsub -all { +} [string tolower $folder_name] {_} name + + #return [list $name $folder_name $parent_id $user_id $creation_ip] + + db_transaction { + + # create the folder + + set folder_id [db_exec_plsql folder_create { + select lors__new_folder (:name, :folder_name, :parent_id, :user_id, :creation_ip); + }] + + } on_error { + ad_return_error "Error inserting folder" "The error was: $errmsg" + ad_script_abort + } + return $folder_id +} + +ad_proc -public lors::cr::add_files { + {-parent_id:required} + {-files:required} + {-indb_p:required} +} { + Adds a bunch of files to a folder in the CR + Returns a list with full_path_to_file, mime-type, parent_id, + file_id, version_id, cr_file, file size. + + @param parent_id Folder's parent_id where the files will be put + @param files All files for the parent_id folder come in one list + @param indb_p Whether this file-storage instance (we are about to use) stores files in the file system or in the db + +} { + + # Get the user + set user_id [ad_conn user_id] + + # Get the ip + set creation_ip [ad_conn peeraddr] + + set retlist [list] + foreach fle $files { + + regexp {[^//\\]+$} $fle filename + # Get the filename part of the upload file +# if { ![regexp {[^//\\]+$} $fle filename] } { + # no match +# set filename $fle +# } + + # Get the title + #if { [empty_string_p $title] } { + set title $filename + #} + + set mime_type [cr_filename_to_mime_type -create $fle] + + #return [list $filename $parent_id $user_id $creation_ip $mime_type] + + # insert file into the CR + db_transaction { + + # create the file_id +# set file_id [db_exec_plsql file_add { +# select lors__new_lo (:filename, :parent_id, :user_id, :creation_ip); +# }] + set description "uploaded using LORs" + + # add file + set file_id [db_exec_plsql file_add { + select file_storage__new_file ( + :title, -- title + :parent_id, -- parent_id + :user_id, -- creation_user + :creation_ip, -- creation_ip + false -- indb_p + ); + }] + + # create the revision + # set version_id [db_exec_plsql new_version { + # select lors__new_lo_version (:filename, :filename, :mime_type, :file_id, :user_id, :creation_ip); + # }] + + # add revision + set version_id [db_exec_plsql new_version { + select file_storage__new_version ( + :filename, -- filename + :description, -- description + :mime_type, -- mime_type + :file_id, -- item_id + :user_id, -- creation_user + :creation_ip -- creation_ip + ); + }] + + # move the actual file into the CR + set cr_file [cr_create_content_file $file_id $version_id $fle] + # get the size + set file_size [cr_file_size $cr_file] + + # update the file path in the CR and the size on cr_revisions + db_dml update_revi "update cr_revisions set content = '$cr_file', content_length = $file_size where revision_id = :version_id" + + } + + lappend retlist [list $fle $mime_type $parent_id $file_id $version_id $cr_file $file_size] + } + return $retlist +} \ No newline at end of file Index: openacs-4/packages/lors/tcl/lors-imscp-blackboard5-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/lors-imscp-blackboard5-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/tcl/lors-imscp-blackboard5-procs.tcl 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,212 @@ +ad_library { + IMS Content Packaging functions + + @creation-date 2003-10-13 + @author Ernie Ghiglione (ErnieG@mm.st) + @cvs-id $Id: lors-imscp-blackboard5-procs.tcl,v 1.1 2004/04/22 03:42:06 ernieg Exp $ + +} + +# +# Copyright (C) 2004 Ernie Ghiglione +# +# This package is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# It is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# + +namespace eval lors::imscp::bb {} + +ad_proc -public lors::imscp::bb::getTitle { + -node:required +} { + Gets the title for a Blackboard course + + @option node XML node + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set title_node [$node child all TITLE] + if {![empty_string_p title_node]} { + set title [lors::imsmd::getAtt $title_node value] + return $title + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getDescription { + -node:required +} { + Gets the description for a Blackboard course + + @option node XML node + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set desc_node [$node child all DESCRIPTION] + if {![empty_string_p desc_node]} { + set desc [lors::imsmd::getElement $desc_node] + return $desc + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getDates { + -node:required +} { + Gets the dates for a Blackboard course + + @option node XML node + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set dates_node [$node child all DATES] + if {![empty_string_p dates_node]} { + set created [$dates_node child all CREATED] + set updated [$dates_node child all UPDATED] + return [list [lors::imsmd::getAtt $created value] [lors::imsmd::getAtt $updated value]] + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getFlags { + -name:required + -node:required +} { + Gets the flags for a Blackboard course + + @option name Name of the attribute to get + @option node XML node + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set flags_node [$node child all FLAGS] + if {![empty_string_p flags_node]} { + set getname [$flags_node child all [string toupper $name]] + + if {![empty_string_p getname]} { + return [lors::imsmd::getAtt $getname value] + } else { + return "" + } + + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getNavigationItems { + -node:required +} { + Gets the Navigation items for a Blackboard course + + @option name Name of the attribute to get + @option node XML node + + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set navigation [$node child all [string toupper NAVIGATION]] + if {![empty_string_p flags_node]} { + + set items [$navigation child all ITEM] + set item_list [list] + + foreach item $items { + set item_value [lors::imsmd::getAtt $item value] + set item_label [lors::imsmd::getAtt $item label] + set item_issecure [lors::imsmd::getAtt $item issecure] + set item_isavailable [lors::imsmd::getAtt $item isavailable] + + lappend item_list [list $item_value $item_label $item_issecure $item_isavailable] + } + return $item_list + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getOriginInfo { + -name:required + -node:required +} { + Gets the Blackboard Info from a Blackboard course + + @option name Name of the attribute to get + @option node XML node + @author Ernie Ghiglione (ErnieG@mm.st) +} { + set flags_node [$node child all ORIGININFO] + if {![empty_string_p flags_node]} { + set getname [$flags_node child all [string toupper $name]] + + if {![empty_string_p getname]} { + return [lors::imsmd::getAtt $getname value] + } else { + return "" + } + + } else { + return "" + } +} + +ad_proc -public lors::imscp::bb::getUsers { + -file:required +} { + Gets the Blackboard users from the XML resource file where the user info is. + Returns a list of user attributes + + @option file File and filepath to XML file + @author Ernie Ghiglione (ErnieG@mm.st) +} { + + set docx [dom parse [read [open $file]]] + set usersnode [$docx documentElement] + + set userlist [list] + set emails [list] + foreach user [$usersnode child all USER] { + + set user_id [$user getAttribute id] + set login_id [[$user getElementsByTagName LOGINID] getAttribute value] + set passphrase [[$user getElementsByTagName PASSPHRASE] getAttribute value] + set last_names [[$user getElementsByTagName FAMILY] getAttribute value] + set first_names [[$user getElementsByTagName GIVEN] getAttribute value] + set email [[$user getElementsByTagName EMAIL] getAttribute value] + +# For testing purpose only... has to be removed later + + set email $login_id@box.com + +# + + set creation_date [[$user getElementsByTagName CREATED] getAttribute value] + set updated_date [[$user getElementsByTagName UPDATED] getAttribute value] + set active [[$user getElementsByTagName ISAVAILABLE] getAttribute value] + set role_value [string tolower [[$user getElementsByTagName ROLE] getAttribute value]] + + switch $role_value { + instructor { + set role "professor" + } + default { + set role "student" + } + } + + set role_description [[$user getElementsByTagName ROLE] getAttribute description] + + lappend userlist [list "user_id" $user_id "login_id" $login_id "passphrase" $passphrase "last_names" $last_names "first_names" $first_names "email" $email \ + "creation_date" $creation_date "updated_date" $updated_date "active" $active "role" $role "role_description" $role_description] + + } + + return $userlist + +} + Index: openacs-4/packages/lors/tcl/lors-imscp-procs-postgres.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/Attic/lors-imscp-procs-postgres.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/tcl/lors-imscp-procs-postgres.xql 22 Apr 2004 03:42:06 -0000 1.1 @@ -0,0 +1,22 @@ + + + + postgresql7.1 + + + + select ims_manifest__new ( + :man_id, + :identifier, + :version, + :orgs_default, + :hasmetadata, + :parent_man_id, + current_timestamp, + :user_id, + :creation_ip, + :package_id + ) + + + Index: openacs-4/packages/lors/tcl/lors-imscp-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/lors-imscp-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/tcl/lors-imscp-procs.tcl 22 Apr 2004 03:42:07 -0000 1.1 @@ -0,0 +1,881 @@ +ad_library { + IMS Content Packaging functions + + @creation-date 2003-10-13 + @author Ernie Ghiglione (ErnieG@mm.st) + @cvs-id $Id: lors-imscp-procs.tcl,v 1.1 2004/04/22 03:42:07 ernieg Exp $ + +} + +# +# Copyright (C) 2004 Ernie Ghiglione +# +# This package is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# It is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# + +namespace eval lors::imscp {} + +## begin IMS CP XML extraction and processing + + # IMS CP XML extraction + +ad_proc -public lors::imscp::getItems { + {tree} + {parent ""} +} { + Extracts data from Items + + @option tree the XML node that contains the Items to get. + @option parent parent item node (items can have subitems). + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + set items "" + set itemx [$tree child all item] + + if { ![empty_string_p $itemx] } { + + if {[empty_string_p $parent]} { + set parent 0 + } + + foreach itemx [$tree child all item] { + + set cc "{$parent}" + # gets item identifier + set cc [concat $cc "{[lors::imsmd::getAtt $itemx identifier]}"] + + # gets item identifierref + set cc [concat $cc "{[lors::imsmd::getAtt $itemx identifierref]}"] + + # gets item isvisible ? + set cc [concat $cc "{[lors::imsmd::getAtt $itemx isvisible]}"] + + # parameters + set cc [concat $cc "{[lors::imsmd::getAtt $itemx parameters]}"] + + # gets item title + set title [$itemx child all title] + if {![empty_string_p $title]} { + set cc [concat $cc "[lors::imsmd::getElement $title]"] + } else { + set cc [concat $cc "{}"] + } + + # has metadata? + if {[lors::imsmd::hasMetadata $itemx] == 1} { + set cc [concat $cc [lors::imsmd::getMDNode $itemx]] + } else { + set cc [concat $cc 0] + } + # set cc [concat $cc [lors::imsmd::hasMetadata $itemx]] + + ## SCORM Extensions + # prerequisites + set prerequisites [$itemx child all adlcp:prerequisites] + if {![empty_string_p $prerequisites]} { + set type [lors::imsmd::getAtt $prerequisites type] + if {![empty_string_p $type]} { + set bb $type + } else { + set bb "{}" + } + set cc [concat $cc "{ {$bb} {[lors::imsmd::getElement $prerequisites]}}"] + } else { + set cc [concat $cc "{{} {}}"] + } + + # maxtimeallowed + set maxtimeallowed [$itemx child all adlcp:maxtimeallowed] + if {![empty_string_p $maxtimeallowed]} { + set cc [concat $cc "{[lors::imsmd::getElement $maxtimeallowed]}"] + } else { + set cc [concat $cc "{}"] + } + + # timelimitaction + set timelimitaction [$itemx child all adlcp:timelimitaction] + if {![empty_string_p $timelimitaction]} { + set cc [concat $cc "{[lors::imsmd::getElement $timelimitaction]}"] + } else { + set cc [concat $cc "{}"] + } + + # datafromlms + set datafromlms [$itemx child all adlcp:datafromlms] + if {![empty_string_p $datafromlms]} { + set cc [concat $cc "{[lors::imsmd::getElement $datafromlms]}"] + } else { + set cc [concat $cc "{}"] + } + + # masteryscore + set masteryscore [$itemx child all adlcp:masteryscore] + if {![empty_string_p $masteryscore]} { + set cc [concat $cc "{[lors::imsmd::getElement $masteryscore]}"] + } else { + set cc [concat $cc "{}"] + } + + set itemxx [$itemx child all item] + if { ![empty_string_p $itemxx] } { + incr parent + set cc [concat $cc [list [getItems $itemx $parent]]] + incr parent -1 + } + set items [concat $items [list $cc]] + } + } + return $items +} + + # end IMS CP XML extraction + + +ad_proc -public lors::imscp::countItems { + {tree} +} { + Counts number of items. + Returns an integer. + + @option tree the XML node that contains the Items to get. + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + return [llength [$tree getElementsByTagName item]] + +} + + + # IMS CP database transaction functions +ad_proc -public lors::imscp::manifest_add { + {-man_id ""} + {-identifier ""} + {-course_name ""} + {-version ""} + {-orgs_default {}} + {-hasmetadata ""} + {-parent_man_id ""} + {-isscorm ""} + {-folder_id ""} + {-fs_package_id ""} + {-package_id ""} + {-user_id ""} + {-creation_ip ""} + +} { + Inserts a new manifest according to the imsmanifest.xml file. + + @option man_id manifest id to be inserted. + @option course_name the actual name of the course (or resource). + @option identifier intrinsic manifest identifier. + @option version version. + @option orgs_default default organizations value. + @option hasmetadata whether the manifest has metadata (boolean). + @option parent_man_id parent manifest id (for manifest with submanifests). + @option isscorm wheather the manifest is SCORM compliant + @option folder_id the CR folder ID we created to put the manifest on. + @option package_id Package id. + @option user_id user that adds the category. [ad_conn user_id] used by default. + @option creation_ip ip-address of the user that adds the category. [ad_conn peeraddr] used by default. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + if {[empty_string_p $creation_ip]} { + set creation_ip [ad_conn peeraddr] + } + if {[empty_string_p $package_id]} { + set package_id [ad_conn package_id] + } + if {[empty_string_p $parent_man_id]} { + set parent_man_id 0 + } + if {[empty_string_p $isscorm]} { + set isscorm 0 + } + + db_transaction { + set manifest_id [db_exec_plsql new_manifest { + select ims_manifest__new ( + :man_id, + :course_name, + :identifier, + :version, + :orgs_default, + :hasmetadata, + :parent_man_id, + :isscorm, + :folder_id, + :fs_package_id, + current_timestamp, + :user_id, + :creation_ip, + :package_id + ); + + } + ] + + } + return $manifest_id +} + +ad_proc -public lors::imscp::manifest_delete { + -man_id:required +} { + Deletes a manifest. + + @option man_id manifest id to be inserted. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set ret [db_exec_plsql delete_manifest { + select ims_manifest__delete ( + :man_id + ); + + } + ] + } + return $ret +} + +ad_proc -public lors::imscp::organization_add { + {-org_id ""} + -man_id:required + {-identifier ""} + {-structure ""} + {-title ""} + {-hasmetadata ""} + {-package_id ""} + {-user_id ""} + {-creation_ip ""} + +} { + Inserts a new organizations according to the imsmanifest.xml file. + + @option org_id organization id to be inserted. + @option man_id manifest_id the organization belogs to. + @option identifier intrinsic organization identifier. + @option structure organization structure. + @option title organization title. + @option hasmetadata whether the organization has metadata (boolean). + @option package_id Package id. + @option user_id user that adds the category. [ad_conn user_id] used by default. + @option creation_ip ip-address of the user that adds the category. [ad_conn peeraddr] used by default. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + if {[empty_string_p $creation_ip]} { + set creation_ip [ad_conn peeraddr] + } + if {[empty_string_p $package_id]} { + set package_id [ad_conn package_id] + } + + db_transaction { + set organization_id [db_exec_plsql new_organization { + select ims_organization__new ( + :org_id, + :man_id, + :identifier, + :structure, + :title, + :hasmetadata, + current_timestamp, + :user_id, + :creation_ip, + :package_id + ); + + } + ] + + } + return $organization_id +} + +ad_proc -public lors::imscp::organization_delete { + -org_id:required +} { + Deletes a Organization. + + @option org_id organization id to be inserted. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set ret [db_exec_plsql delete_organization { + select ims_organization__delete ( + :org_id + ); + + } + ] + + } + return $ret +} + +ad_proc -public lors::imscp::item_add { + {-item_id ""} + -org_id:required + {-identifier ""} + {-identifierref ""} + {-isvisible ""} + {-parameters ""} + {-title ""} + {-parent_item ""} + {-hasmetadata ""} + {-prerequisites_t ""} + {-prerequisites_s ""} + {-type ""} + {-maxtimeallowed ""} + {-timelimitaction ""} + {-datafromlms ""} + {-masteryscore ""} + {-package_id ""} + {-user_id ""} + {-creation_ip ""} + +} { + Inserts a new item according to the info retrieved from the imsmanifest.xml file. + + @option item_id item id to be inserted. + @option org_id organization_id the item belogs to. + @option identifier intrinsic item identifier. + @option identifierref items indentifier reference (use to map with resources) + @option isvisible is the item visible?. + @option parameters items parameters + @option title items title. + @option parent_item for recursive items. Items can have subitems. + @option hasmetadata whether the item has metadata (boolean). + @option prerequisites_t items prerequisites type (SCORM extension). + @option prerequisites_s items prerequisites string (SCORM extension). + @option type items type (SCORM extension). + @option maxtimeallowed items maximum time allowed (SCORM extension). + @option timelimitaction items time limit action (SCORM extension). + @option datafromlms items data from LMS (SCORM extension). + @option masteryscore items mastery score (SCORM extension). + @option package_id Package id. + @option user_id user that adds the category. [ad_conn user_id] used by default. + @option creation_ip ip-address of the user that adds the category. [ad_conn peeraddr] used by default. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + if {[empty_string_p $creation_ip]} { + set creation_ip [ad_conn peeraddr] + } + if {[empty_string_p $package_id]} { + set package_id [ad_conn package_id] + } + if {[empty_string_p $isvisible]} { + set isvisible 1 + } + if {$parent_item == 0} { + set parent_item $org_id + } + if {[empty_string_p $title]} { + set title "No Title" + } + + db_transaction { + set item_id [db_exec_plsql new_item { + select ims_item__new ( + :item_id, + :org_id, + :identifier, + :identifierref, + :isvisible, + :parameters, + :title, + :parent_item, + :hasmetadata, + :prerequisites_t, + :prerequisites_s, + :type, + :maxtimeallowed, + :timelimitaction, + :datafromlms, + :masteryscore, + current_timestamp, + :user_id, + :creation_ip, + :package_id + ); + + } + ] + + } + return $item_id +} + +ad_proc -public lors::imscp::item_delete { + -item_id:required +} { + Deletes a Item. + + @option item_id item id to be removed. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set ret [db_exec_plsql delete_item { + select ims_item__delete ( + :item_id + ); + + } + ] + + } + return $ret +} + +ad_proc -public lors::imscp::addItems { + {-org_id:required} + {itemlist} + {parent ""} + {tmp_dir ""} +} { + Bulk addition of items. + Returns a list with the item_id and the identifierref of each item. + + @option org_id Organization Id that the item belongs to. + @option itemlist list of items to be uploaded + @option parent parent item node (items can have subitems). + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + set retlist "" + + foreach item $itemlist { + set p_org_id $org_id + set p_parent_item $parent + set p_identifier [lindex $item 1] + set p_identifierref [lindex $item 2] + set p_isvisible [lindex $item 3] + set p_parameters [lindex $item 4] + set p_title [lindex $item 5] + set p_hasmetadata [lindex $item 6] + set p_prerequisites [lindex $item 7] + set p_prerequisites_type [lindex $p_prerequisites 0] + set p_prerequisites_string [lindex $p_prerequisites 1] + set p_maxtimeallowed [lindex $item 8] + set p_timelimitaction [lindex $item 9] + set p_datafromlms [lindex $item 10] + set p_masteryscore [lindex $item 11] + + if {$p_hasmetadata != 0} { + set md_node $p_hasmetadata + set p_hasmetadata 1 + } + + set item_id [lors::imscp::item_add \ + -org_id $p_org_id \ + -parent_item $p_parent_item \ + -identifier $p_identifier \ + -identifierref $p_identifierref \ + -isvisible $p_isvisible \ + -title $p_title \ + -hasmetadata $p_hasmetadata \ + -prerequisites_t $p_prerequisites_type \ + -prerequisites_s $p_prerequisites_string \ + -maxtimeallowed $p_maxtimeallowed \ + -timelimitaction $p_timelimitaction \ + -datafromlms $p_datafromlms \ + -masteryscore $p_masteryscore] + + if {$p_hasmetadata == 1} { + set aa [lors::imsmd::addMetadata \ + -acs_object $item_id \ + -node $md_node \ + -dir $tmp_dir] + } + + lappend retlist [list $item_id $p_identifierref] + + if { [llength $item] > 12} { + set subitem [lors::imscp::addItems -org_id $p_org_id [lindex $item 12] $item_id $tmp_dir] + set retlist [concat $retlist $subitem] + } + } + return $retlist +} + + +ad_proc -public lors::imscp::resource_add { + {-res_id ""} + -man_id:required + {-identifier ""} + {-type ""} + {-href ""} + {-scorm_type ""} + {-hasmetadata ""} + {-package_id ""} + {-user_id ""} + {-creation_ip ""} + +} { + Inserts a new resource according to the imsmanifest.xml file. + + @option res_id resource id to be inserted. + @option man_id manifest the resource belogs to (required). + @option identifier intrinsic item identifier. + @option type item type. + @option href location or references to item location. + @option scorm_type SCORM item type (SCORM extension). + @option hasmetadata whether the item has metadata (boolean). + @option package_id Package id. + @option user_id user that adds the category. [ad_conn user_id] used by default. + @option creation_ip ip-address of the user that adds the category. [ad_conn peeraddr] used by default. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + if {[empty_string_p $creation_ip]} { + set creation_ip [ad_conn peeraddr] + } + if {[empty_string_p $package_id]} { + set package_id [ad_conn package_id] + } + + db_transaction { + set resource_id [db_exec_plsql new_resource { + select ims_resource__new ( + :res_id, + :man_id, + :identifier, + :type, + :href, + :scorm_type, + :hasmetadata, + current_timestamp, + :user_id, + :creation_ip, + :package_id + ); + + } + ] + + } + return $resource_id +} + +ad_proc -public lors::imscp::resource_delete { + -res_id:required +} { + Deletes a Resource. + + @option res_id resource id to be removed. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set ret [db_exec_plsql delete_resource { + select ims_resource__delete ( + :res_id + ); + + } + ] + } + return $ret +} + +ad_proc -public lors::imscp::item_to_resource_add { + -item_id:required + -res_id:required +} { + Adds a relationship btw items and resources + + @option item_id the item_id to relate to the resource + @option res_id the resource id + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set item_to_resource [db_exec_plsql item_to_resources_add { + select ims_cp_item_to_resource__new ( + :item_id, + :res_id + ); + } + ] + } + return $item_to_resource +} + + +ad_proc -public lors::imscp::dependency_add { + -res_id:required + -identifierref:required +} { + Adds a resource dependency + + @option res_id the resource id that the dependency belongs to. + @option identifier dependency identifier. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set dep_id [db_nextval ims_cp_dependencies_seq] + set dependency [db_exec_plsql dependency_add { + select ims_dependency__new ( + :dep_id, + :res_id, + :identifierref + ); + } + ] + } + return $dep_id +} + +ad_proc -public lors::imscp::dependency_delete { + -dep_id:required +} { + Deletes a dependency + + @option dep_id dependency id to be removed. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + db_transaction { + set ret [db_exec_plsql delete_resource { + select ims_dependency__delete ( + :dep_id + ); + + } + ] + } + return $ret +} + + +ad_proc -public lors::imscp::file_add { + -file_id:required + -res_id:required + -pathtofile:required + -filename:required + {-hasmetadata ""} +} { + Adds a files to ims_cp_files table (Note: we are not adding files to the respository here). + + @option file_id file_id for file (cr_revision). + @option res_id the resource id. + @option pathtofile original path to file as described on the imsmanifest.xml. + @option filename file name. + @option hasmetadata file metadata (boolean). + @author Ernie Ghiglione (ErnieG@mm.st) +} { + if {[empty_string_p $hasmetadata]} { + set hasmetadata 0 + } + db_transaction { + set file [db_exec_plsql file_add { + select ims_file__new ( + :file_id, + :res_id, + :pathtofile, + :filename, + :hasmetadata + ); + } + ] + } + return $file_id +} + + + # end IMS CP database transaction functions + +## end IMS CP XML extraction and processing + + +### CP procedures that deal with file processing + +ad_proc -public lors::imscp::open {} { + + Installing IMS/SCORM Service Contracts + +} { + return "this thing is open now" + +} + +ad_proc -public lors::imscp::expand_file { + upload_file + tmpfile + {dest_dir_base "extract"} +} { + Given an uploaded file in file tmpfile with original name upload_file + extract the archive and put in a tmp directory which is the return value + of the function + + @param upload_file path to the uploaded file + @param tmpfile temporary file name + @option dest_dir_base name of the directory where the files will be extracted to + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + set tmp_dir [file join [file dirname $tmpfile] [ns_mktemp "$dest_dir_base-XXXXXX"]] + if [catch { ns_mkdir $tmp_dir } errMsg ] { + ns_log Notice "LORS::imscp::expand_file: Error creating directory $tmp_dir: $errMsg" + return -code error "LORS::imscp::expand_file: Error creating directory $tmp_dir: $errMsg" + } + + set upload_file [string trim [string tolower $upload_file]] + + if {[regexp {(.tar.gz|.tgz)$} $upload_file]} { + set type tgz + } elseif {[regexp {.tar.z$} $upload_file]} { + set type tgZ + } elseif {[regexp {.tar$} $upload_file]} { + set type tar + } elseif {[regexp {(.tar.bz2|.tbz2)$} $upload_file]} { + set type tbz2 + } elseif {[regexp {.zip$} $upload_file]} { + set type zip + } else { + set type "Uknown type" + } + + switch $type { + tar { + set errp [ catch { exec tar --directory $tmp_dir -xvf $tmpfile } errMsg] + } + tgZ { + set errp [ catch { exec tar --directory $tmp_dir -xZvf $tmpfile } errMsg] + } + tgz { + set errp [ catch { exec tar --directory $tmp_dir -xzvf $tmpfile } errMsg] + } + tbz2 { + set errp [ catch { exec tar --directory $tmp_dir -xjvf $tmpfile } errMsg] + } + zip { + set errp [ catch { exec unzip -d $tmp_dir $tmpfile } errMsg] + } + default { + set errp 1 + set errMsg "dont know how to extract $upload_file" + } + } + + if {$errp} { + file delete -force $tmp_dir + ns_log Notice "lors::imscp::expand_file: extract type $type failed $errMsg" + return -code error "lors::imscp::expand_file: extract type $type failed $errMsg" + } + return $tmp_dir +} + +ad_proc -public lors::imscp::dir_walk { + dir +} { + Walk starting at a given directory and return a list + of all the plain files found + + @param dir Directory to walk thru + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + set files [list] + foreach f [glob -nocomplain [file join $dir *]] { + set type [file type $f] + switch $type { + directory { + set files [concat $files [lors::imscp::dir_walk $f]] + } + file { + lappend files $f + } + default { + # Goofy file types -- just ignore them + } + } + } + return $files +} + + +ad_proc -public lors::imscp::findmanifest { + tmp_dir + file +} { + Find the manifest file or other file that contains + the information about the course. + if it finds it, then it returns the file location. Otherwise it + returns 0 + + @param tmp_dir Temporary directory where the course is located + @param file Manifest file + @author Ernie Ghiglione (ErnieG@mm.st) + +} { + if {[file exist $tmp_dir/$file]} { + return "$tmp_dir/$file" + } else { + return 0 + } +} + + +ad_proc -public lors::imscp::deltmpdir { + tmp_dir +} { + Deletes the course from the file system once it has been dealt with + + @option tmp_dir temporary directory to be deleted. + @author Ernie Ghiglione (ErnieG@mm.st) +} { + #Now that we are done working on the upload we delete the tmp directory and files + if [info exists tmp_dir] { + ns_log Notice "lors::imscp: Deleting $tmp_dir" + file delete -force $tmp_dir + } +} + +ad_proc -public lors::imscp::isSCORM { + -node:required +} { + Checks it the node past has SCORM Content Packaging extension. + + @option node XML node to analyze. + @author Ernie Ghiglione (ErnieG@mm.st). +} { + # Checks the manifest attribute + + set man_attribute [$node hasAttribute xmlns:adlcp] + + # Checks manifest metadata schema + set metadata [$node child all metadata] + + if {![empty_string_p $metadata]} { + set MetadataSchema [lindex [lindex [lors::imsmd::getMDSchema $metadata] 0] 0] + set man_scorm_metadataschema [regexp -nocase scorm $MetadataSchema] + } else { + return 0 + } + + if {$man_attribute == 1 || $man_scorm_metadataschema == 1} { + # It's a SCORM CP + return 1 + } else { + return 0 + } + +} Index: openacs-4/packages/lors/tcl/lors-imsmd-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/lors-imsmd-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/lors/tcl/lors-imsmd-procs.tcl 22 Apr 2004 03:42:08 -0000 1.1 @@ -0,0 +1,1822 @@ +ad_library { + + IMS Metadata functions + + @author Ernie Ghiglione (ErnieG@mm.st) + @creation-date 13 Oct 2003 + @cvs-id $Id: lors-imsmd-procs.tcl,v 1.1 2004/04/22 03:42:08 ernieg Exp $ + +} + +# +# Copyright (C) 2004 Ernie Ghiglione +# +# This package is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# It is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# + +namespace eval lors::imsmd { + + ad_proc -public getAtt {doc attr_name} { + getAtt Gets attributes for an specific element + + @param doc Document + @param attr_name Attribute we want to fetch + + } { + if {[$doc hasAttribute $attr_name] == 1} { + $doc getAttribute $attr_name + } else { + return "" + } + } + + ad_proc -public HasPrefix { + {tree} + } { + Checks if the XML node contains a namespace prefix + returns prefix or returns "" if false. + + @param tree The node + + } { + set prefix [$tree prefix] + return $prefix + } + + ad_proc -public hasMetadata { + {tree} + } { + Checks if the XML node contains a metadata element + returns 1 if true; 0 if false. + Later addition: checks also if the metadata record has + child nodes + } { + if { ![empty_string_p [$tree child all metadata]] } { + if { [[$tree child all metadata] hasChildNodes] != 0 } { + return 1 + } else { + return 0 + } + } else { + return 0 + } + } + + ad_proc -public getMDNode { + {tree} + } { + Returns the metadata node + + @param tree The Node + + } { + return [$tree child all metadata] + } + + ad_proc -public getMDSchema { + {tree} + } { + Gets the type of MD Schema used (if any) + Returns 0 if not found or + returns a list with 2 elements: + \{Schema\} \{Schemaversion\} + + @param tree The Node + + } { + if { [$tree hasChildNodes] == 1 } { + set retlist [list] + if { ![empty_string_p [$tree child all schema]] } { + lappend retlist [getElement [$tree child all schema] asXML] + } + if { ![empty_string_p [$tree child all schemaversion]] } { + lappend retlist [getElement [$tree child all schemaversion]] + } + return $retlist + } else { + return [list 0 0] + } + } + + ad_proc -public getLOM { + {tree} + {dir} + } { + Gets the Node where LOM is and its prefix (if any) + returns a list with two elements: + \{LOM_Node\} \{prefix\} + or if didn't find any, returns 0 + + @param tree The Node. + @param dir Directory where the course is. + @author Ernie Ghiglione (ErnieG@mm.st). + + } { + if { ![$tree hasChildNodes] == 0 } { + if { ![empty_string_p [$tree child all lom]] } { + set var_lom "lom" + set prefix "" + set lom [$tree child all $var_lom] + } elseif { ![empty_string_p [$tree child all imsmd:lom]] } { + set var_lom "imsmd:lom" + set prefix [[$tree child all imsmd:lom] prefix] + set lom [$tree child all $var_lom] + } elseif { ![empty_string_p [$tree child all record]] } { + # used mostly for IMS Metadata + set var_lom "record" + set prefix "" + set lom [$tree child all $var_lom] + } elseif { ![empty_string_p [$tree child all imsmd:record]] } { + # used mostly for IMS Metadata + set var_lom "imsmd:record" + set prefix [[$tree child all imsmd:record] prefix] + set lom [$tree child all $var_lom] + } elseif { ![empty_string_p [$tree child all adlcp:location]] } { + set lom [[dom parse [read [open $dir/[[$tree child all adlcp:location] text]]]] documentElement] + set prefix [$lom prefix] + } else { + set lom 0 + set prefix 0 + } + return [list $lom $prefix] + } else { + return 0 + } + } + + # xmlExtractor extras + ad_proc -public xmlExtractor { + {element} + {tree} + {prefix {}} + {datatype 0} + {att {}} + } { + XML Metadata extractor + This is the key MD extractor. + + It uses some different datatypes to extract MD: + + datatype1 = langstrings + datatype2 = source and values + datatype3 = catalogentry + datatype4 = date + datatype5 = Vcards + datatype6 = element + attributes + datatype7 = element + + @param element + @param tree + @param prefix + @param datatype + @param att + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { [empty_string_p $prefix] } { + set md_g_title [$tree child all $element] + } else { + set md_g_title [$tree child all $prefix:$element] + } + if { ![empty_string_p $md_g_title] } { + set retlist [list] + if {$datatype == 1} { + foreach one $md_g_title { + #gets langstrings + set retlist "$retlist [getLangStr $one $prefix]" + } + return $retlist + } elseif {$datatype == 2} { + foreach one $md_g_title { + #get sources and values + set retlist "$retlist [getSourceValue $one $prefix]" + } + return $retlist + } elseif {$datatype == 3} { + foreach one $md_g_title { + #get catalogentry + set retlist "$retlist [getCatalogEntry $one $prefix]" + } + return $retlist + } elseif {$datatype == 4} { + foreach one $md_g_title { + #get date + set retlist "$retlist [getDate $one $prefix]" + } + return $retlist + } elseif {$datatype == 5} { + foreach one $md_g_title { + #get person / Vcard + set retlist "$retlist [getVcard $one $prefix]" + } + return $retlist + } elseif {$datatype == 6} { + foreach one $md_g_title { + #get element attribute only. + set retlist "$retlist [getAtt $one $att]" + } + return $retlist + } else { + foreach one $md_g_title { + #get simple element + set retlist "$retlist [getElement $one $prefix $att]" + } + return $retlist + } + } + + } + + + ### Datatypes ad_procedures + + ad_proc -public getLangStr { + {tree} + {prefix {}} + } { + Datatype LangString extractor + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var "$prefix:langstring" + } else { + set var "langstring" + } + set aa [list] + set ab [list] + set mult 0 + foreach child [$tree child all $var] { + #set aa "$aa | [$child localName] (xml:lang=[getAtt $child xml:lang]) [$child text]" + # returns a list with lang and string (LangString) + set aa [list [getAtt $child xml:lang] [$child text]] + lappend ab $aa + incr mult + } + if { $mult > 1} { + return $ab + } else { + return $ab + } + } + + ad_proc -public getSourceValue { + {tree} + {prefix {}} + } { + Datatype Source&Value extractor + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_source "$prefix:source" + set var_value "$prefix:value" + } else { + set var_source "source" + set var_value "value" + } + set source [$tree child all $var_source] + set sv [list] + if { ![empty_string_p $source] } { + #Gets all the langstrings + set sv "$sv [getLangStr $source $prefix]" + } + set value [$tree child all $var_value] + if { ![empty_string_p $value] } { + #Gets all the langstrings + set sv "$sv [getLangStr $value $prefix]" + } + return [list $sv] + } + + + ad_proc -public getCatalogEntry { + {tree} + {prefix {}} + } { + Datatype CatalogEntry extractor + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_catalog "$prefix:catalog" + set var_entry "$prefix:entry" + } else { + set var_catalog "catalog" + set var_entry "entry" + } + set catalog [$tree child all $var_catalog] + set ce [list] + if { ![empty_string_p $catalog] } { + #Gets all the langstrings + set ce "$ce [getElement $catalog $prefix]" + } + set entry [$tree child all $var_entry] + if { ![empty_string_p $entry] } { + #Gets all the langstrings + set ce "$ce [lors::imsmd::getLangStr $entry $prefix]" + } + return [list $ce] + } + + ad_proc -public getDate { + {tree} + {prefix {}} + } { + Datatype Date + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_datetime "$prefix:datetime" + set var_description "$prefix:description" + } else { + set var_datetime "datetime" + set var_description "description" + } + set datetime [$tree descendant all $var_datetime] + set dt "" + if { ![empty_string_p $datetime] } { + #Gets all the langstrings + set dt [getElement $datetime $prefix] + } + set description [$tree descendant all $var_description] + if { ![empty_string_p $description] } { + #Gets all the langstrings + set dt "$dt [getLangStr $description $prefix]" + } + return $dt + } + + + + ad_proc -public getElement { + {tree} + {prefix {}} + {att {}} + } { + Datatype Element extractor + + @param tree Node + @param prefix prefix (if any) + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $att] } { + return [list "{[$tree text]} {[getAtt $tree $att]}"] + } else { + return [list [$tree text]] + } + } + + + ad_proc -public getVcard { + {tree} + {prefix {}} + } { + Datatype Vcard + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_vcard "$prefix:vcard" + } else { + set var_vcard "vcard" + } + + foreach child [$tree child all $var_vcard] { + set aa "[$child text]" + } + return [list $aa] + } + + ## Special Datatypes ad_procedures + ad_proc -public getTaxon { + {tree} + {prefix {}} + } { + Special extraction of Taxonomies + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + } { + if { ![empty_string_p $prefix] } { + set var_taxon $prefix:taxon + + } else { + set var_taxon taxon + } + + set taxon [$tree child all $var_taxon] + + if { ![empty_string_p $taxon]} { + set taxons $taxon + foreach one $taxon { + if { ![empty_string_p [$one descendant all $var_taxon]] } { + set taxons "$taxons [getTaxon $one $prefix]" + } + return $taxons + } + } + } + + + ad_proc -public getContribute { + {tree} + {prefix {}} + } { + Special extraction of Contributors + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_contribute "$prefix:contribute" + set var_role "$prefix:role" + set var_centity "$prefix:centity" + set var_date "$prefix:date" + } else { + set var_contribute "contribute" + set var_role "role" + set var_centity "centity" + set var_date "date" + } + set lom_lc_contribute [$tree child all $var_contribute] + if { ![empty_string_p $lom_lc_contribute] } { + set cont_list [list] + foreach contribute [$tree child all $var_contribute] { + set role [$contribute child all $var_role] + if { ![empty_string_p $role] } { + set cont_x [xmlExtractor role $contribute $prefix 2] + } + set centity [$contribute child all $var_centity] + if { ![empty_string_p $centity] } { + set cc [list] + foreach cent $centity { + set cc "$cc [xmlExtractor vcard $cent $prefix ]" + } + set cont_x "$cont_x [list $cc]" + } + set date [$contribute child all $var_date] + if { ![empty_string_p $date] } { + set cont_x "$cont_x [list [xmlExtractor date $contribute $prefix 4]]" + } + lappend cont_list $cont_x + } + return $cont_list + } + } + + ad_proc -public getRequirement { + {tree} + {prefix {}} + } { + Gets requirements + + @param tree Node + @param prefix prefix (if any) + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set var_requirement "$prefix:requirement" + } else { + set var_requirement "requirement" + } + + set lom_te_req [$tree child all $var_requirement] + if { ![empty_string_p $lom_te_req] } { + # there could be multiple req + set ret_list [list] + foreach req [$tree child all $var_requirement] { + set tmpvar [xmlExtractor type $req $prefix 2] + set tmpvar "$tmpvar [xmlExtractor name $req $prefix 2]" + set tmpvar "$tmpvar [xmlExtractor minimumversion $req $prefix]" + set tmpvar "$tmpvar [xmlExtractor maximumversion $req $prefix]" + lappend ret_list $tmpvar + } + return $ret_list + } + } + + ad_proc -public namechild { + {a} + } { + Gets the node names for the children of a particular node + For testing and debugging purposes only + } { + set lix {} + foreach node $a { + foreach child [$node child all] {lappend lix [$child localName] [$child prefix]} + } + return $lix + } + + + ## Metadata extractor function + + + ad_proc -public mdGeneral { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + General Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_g [$node child all $prefix:general] + } else { + set lom_g [$node child all general] + } + if { ![empty_string_p $lom_g] } { + set retlist [list] + switch $element { + title { + #gets title + set retlist [xmlExtractor title $lom_g $prefix 1] + } + catalogentry { + #gets catalogentry + set retlist [xmlExtractor catalogentry $lom_g $prefix 3] + } + language { + #gets language + set retlist [xmlExtractor language $lom_g $prefix] + } + description { + #gets description + set retlist [xmlExtractor description $lom_g $prefix 1] + } + keyword { + #gets keyword + set retlist [xmlExtractor keyword $lom_g $prefix 1] + } + coverage { + #gets coverage + set retlist [xmlExtractor coverage $lom_g $prefix 1] + } + structure { + #gets structure + set retlist [xmlExtractor structure $lom_g $prefix 2] + } + aggregationlevel { + #gets aggregationlevel + set retlist [xmlExtractor aggregationlevel $lom_g $prefix 2] + } + default { + return 0 + } + } + return $retlist + } + return 0 + } + + ad_proc -public mdLifeCycle { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + Life Cycle Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_lc [$node child all $prefix:lifecycle] + } else { + set lom_lc [$node child all lifecycle] + } + if { ![empty_string_p $lom_lc] } { + set retlist [list] + switch $element { + version { + #gets version + set retlist [xmlExtractor version $lom_lc $prefix 1] + } + status { + #gets status + set retlist [xmlExtractor status $lom_lc $prefix 2] + } + contribute { + #gets contribute + set retlist [getContribute $lom_lc $prefix] + } + default { + return 0 + } + } + return $retlist + } + return 0 + } + + ad_proc -public mdMetadata { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + Meta Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_md [$node child all $prefix:metametadata] + } else { + set lom_md [$node child all metametadata] + } + if { ![empty_string_p $lom_md] } { + set retlist [list] + switch $element { + contribute { + #gets contribute + set retlist [getContribute $lom_md $prefix] + } + catalogentry { + #get catalogentry + set retlist [xmlExtractor catalogentry $lom_md $prefix 3] + } + metadatascheme { + #get metadatascheme + set retlist [xmlExtractor metadatascheme $lom_md $prefix] + } + language { + #get language + set retlist [xmlExtractor language $lom_md $prefix] + } + } + return $retlist + } + return 0 + } + + + ad_proc -public mdTechnical { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + Technical Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_te [$node child all $prefix:technical] + } else { + set lom_te [$node child all technical] + } + if { ![empty_string_p $lom_te] } { + set retlist [list] + switch $element { + format { + #gets format + set retlist [xmlExtractor format $lom_te $prefix] + } + location { + #gets location + set retlist [xmlExtractor location $lom_te $prefix 0 type] + } + requirement { + #gets requiremets + set retlist [getRequirement $lom_te $prefix] + } + size { + #gets size + set retlist [xmlExtractor size $lom_te $prefix 0] + } + installationremarks { + #gets installationremarks + set retlist [xmlExtractor installationremarks $lom_te $prefix 1] + } + otherplatformrequirements { + #gets otherplatformrequirements + set retlist [xmlExtractor otherplatformrequirements $lom_te $prefix 1] + } + duration { + #gets duration + set retlist [xmlExtractor duration $lom_te $prefix 4] + } + default { + return 0 + } + } + return $retlist + } + return 0 + } + + + ad_proc -public mdEducational { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + Educational Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_ed [$node child all $prefix:educational] + } else { + set lom_ed [$node child all educational] + } + if { ![empty_string_p $lom_ed] } { + set retlist [list] + switch $element { + interactivitytype { + #gets format + set retlist [xmlExtractor interactivitytype $lom_ed $prefix 2] + } + learningresourcetype { + #gets learningresourcetype + set retlist [xmlExtractor learningresourcetype $lom_ed $prefix 2] + } + interactivitylevel { + #gets interactivitylevel + set retlist [xmlExtractor interactivitylevel $lom_ed $prefix 2] + } + semanticdensity { + #gets semanticdensity + set retlist [xmlExtractor semanticdensity $lom_ed $prefix 2] + } + intendedenduserrole { + #gets intendedenduserrole + set retlist [xmlExtractor intendedenduserrole $lom_ed $prefix 2] + } + context { + #gets context + set retlist [xmlExtractor context $lom_ed $prefix 2] + } + typicalagerange { + #gets typicalagerange + set retlist [xmlExtractor typicalagerange $lom_ed $prefix 1] + } + difficulty { + #gets difficulty + set retlist [xmlExtractor difficulty $lom_ed $prefix 2] + } + typicallearningtime { + #gets typicallearningtime + set retlist [xmlExtractor typicallearningtime $lom_ed $prefix 4] + } + description { + #gets description + set retlist [xmlExtractor description $lom_ed $prefix 1] + } + language { + #gets language + set retlist [xmlExtractor language $lom_ed $prefix] + } + default { + return 0 + } + } + return $retlist + } + return 0 + } + + + ad_proc -public mdRights { + {-element:required} + {-node:required} + {-prefix {}} + {-att {}} + } { + Rights Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param element element to retrieve + @param node Node + @param prefix Prefix + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_ri [$node child all $prefix:rights] + } else { + set lom_ri [$node child all rights] + } + if { ![empty_string_p $lom_ri] } { + set retlist [list] + switch $element { + cost { + #gets cost + set retlist [xmlExtractor cost $lom_ri $prefix 2] + } + copyrightandotherrestrictions { + #gets copyrightandotherrestrictions + set retlist [xmlExtractor copyrightandotherrestrictions $lom_ri $prefix 2] + } + description { + #gets description + set retlist [xmlExtractor description $lom_ri $prefix 1] + } + default { + return 0 + } + } + return $retlist + } + return 0 + } + + + ad_proc -public mdRelation { + {-node:required} + {-prefix {}} + } { + Relation Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param node Node + @param prefix Prefix + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_re [$node child all $prefix:relation] + } else { + set lom_re [$node child all relation] + } + if { ![empty_string_p $lom_re] } { + set retlist [list] + foreach relation $lom_re { + # Relation can happen 0 to 100 times + #gets kind + set aa "{[lors::imsmd::xmlExtractor kind $relation $prefix 2]}" + #gets resource + if { ![empty_string_p $prefix] } { + set resource [$relation child all $prefix:resource] + } else { + set resource [$relation child all resource] + } + #printx "Resource ([llength $resource]) " $resource + foreach res $resource { + # gets resource description + set aa "$aa {[lors::imsmd::xmlExtractor description $res $prefix 1]}" + # gets resource catalogentry + set aa "$aa {[lors::imsmd::xmlExtractor catalogentry $res $prefix 3]}" + } + lappend retlist $aa + } + return $retlist + } + return 0 + } + + + ad_proc -public mdAnnotation { + {-node:required} + {-prefix {}} + } { + Annotation Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param node Node + @param prefix Prefix + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_an [$node child all $prefix:annotation] + } else { + set lom_an [$node child all annotation] + } + if { ![empty_string_p $lom_an] } { + set retlist [list] + foreach annotation $lom_an { + #gets person + set aa "{[lors::imsmd::xmlExtractor person $annotation $prefix 5]}" + #date + set aa "$aa {[lors::imsmd::xmlExtractor date $annotation $prefix 4]}" + #description + set aa "$aa {[lors::imsmd::xmlExtractor description $annotation $prefix 1]}" + lappend retlist $aa + } + return $retlist + } + return 0 + } + + + ad_proc -public mdClassification { + {-node:required} + {-prefix {}} + } { + Classification Metadata extractor + returns a list with the attributes and elements + if it doesn't exists returns 0 + + @param node Node + @param prefix Prefix + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + if { ![empty_string_p $prefix] } { + set lom_cl [$node child all $prefix:classification] + } else { + set lom_cl [$node child all classification] + } + if { ![empty_string_p $lom_cl] } { + set retlist [list] + set bbcc [list] + foreach classification $lom_cl { + #gets purpose + set aa "{[lors::imsmd::xmlExtractor purpose $classification $prefix 2]}" + + #gets description + set aa "$aa {[lors::imsmd::xmlExtractor description $classification $prefix 1]}" + + #gets taxonpath + if { ![empty_string_p $prefix] } { + set tax [$classification child all $prefix:taxonpath] + } else { + set tax [$classification child all taxonpath] + } + foreach taxonpath $tax { + # gets source + set bb [lors::imsmd::xmlExtractor source $taxonpath $prefix 1] + + # gets taxons + if { ![empty_string_p [lors::imsmd::getTaxon $taxonpath $prefix]] } { + set hierarchy 0 + set cc "" + foreach taxon [lors::imsmd::getTaxon $taxonpath $prefix] { + set cc "$cc {" + set cc "$cc [incr hierarchy]" + set cc "$cc {[lindex [lors::imsmd::xmlExtractor id $taxon $prefix] 0]}" + set cc "$cc {[lindex [lors::imsmd::xmlExtractor entry $taxon $prefix 1] 0]}" + set cc "$cc }" + } + } + lappend bbcc [list $bb $cc] + } + # gets keywords + set dd "{[lors::imsmd::xmlExtractor keyword $classification $prefix 1]}" + + lappend retlist "{$aa [list $bbcc] $dd}" + } + return $retlist + } + return 0 + } + + + + ad_proc -public getResource { + {-node:required} + {-att:required} + } { + Extract data from a resource + -node the XML node + -att the attribute to be extracted + + @param node Node + @param att Attribute + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + switch $att { + scormtype { + # gets the type of resource + return [string tolower [lors::imsmd::getAtt $node adlcp:scormtype]] + } + identifier { + # gets identifier + return [lors::imsmd::getAtt $node identifier] + } + type { + # gets type + return [lors::imsmd::getAtt $node type] + } + href { + # gets href + return [lors::imsmd::getAtt $node href] + } + files { + set files [list] + # gets files + set filex [$node child all file] + if { ![empty_string_p $filex] } { + foreach file $filex { + # checks for file metadata + set file_hasmetadata [lors::imsmd::hasMetadata $file] + if {$file_hasmetadata == 1} { + #if it hasmetadata, then pass the node + set file_hasmetadata [lors::imsmd::getMDNode $file] + } else { + #otherwise, just pass 0 (No metadata found) + set file_hasmetadata 0 + } + lappend files [list [lors::imsmd::getAtt $file href] $file_hasmetadata] + } + } + return $files + } + dependencies { + set dependencies [list] + # gets dependencies + set depende [$node child all dependency] + if { ![empty_string_p $depende] } { + foreach dependex [$node child all dependency] { + lappend dependencies [lors::imsmd::getAtt $dependex identifierref] + } + } + return $dependencies + } + default { + return [lors::imsmd::getAtt $node $att] + } + } + } + + + + ad_proc -public getItem { + {tree} + } { + Extracts data from resource\item + + @param tree Node + @author Ernie Ghiglione (ErnieG@mm.st) + + } { + set itemx [$tree child all item] + + if { ![empty_string_p $itemx] } { + set items [list] + foreach itemx [$tree child all item] { + + # gets item identifier + printx "item identifier: " [getAtt $itemx identifier] + + # gets item identifierref + printx "item identifierref: " [getAtt $itemx identifierref] + + # gets item isvisible ? + printx "item isvisible: " [getAtt $itemx isvisible] + + # gets item title + printx "item title: " [getElement [$itemx child all title]] + + set itemxx [$itemx child all item] + if { ![empty_string_p $itemxx] } { + printx "
" " " + getItem $itemx + printx "
" "" + } + } + } + } + +ad_proc -public addMetadata { + {-acs_object:required} + {-node:required} + {-dir {}} +} { + Adds metadata for a learning resource. + This is the master function for adding metadata. This is the MD mama function. + + @option acs_object acs object for resource (element) that contains metadata. + @option node XML node that contains the metadata + @option dir directory where the imsmanifest.xml file is located. This is use in the case the metadata is in a different file location (adlcp:location). + @author Ernie Ghiglione (ErnieG@mm.st). + +} { + set p_ims_md_id $acs_object + set mdnode $node + set path_to_file $dir + #[lors::imsmd::getMDNode $manifest] + + set p_schema [lindex [lindex [lors::imsmd::getMDSchema $mdnode] 0] 0] + set p_schemaversion [lindex [lors::imsmd::getMDSchema $mdnode] 1] + + + set lom [lindex [lors::imsmd::getLOM $mdnode $path_to_file] 0] + set prefix [lindex [lors::imsmd::getLOM $mdnode $path_to_file] 1] + + + # inserts into db + db_transaction { + + + # Checks if there's a LOM record + if {$lom != 0} { + + # Adds new MD record to ims_md + db_dml add_md { + insert into ims_md (ims_md_id, schema, schemaversion) + values + (:p_ims_md_id, :p_schema, :p_schemaversion) + } + + # General + + # Title + set titles [lors::imsmd::mdGeneral -element title -node $lom -prefix $prefix] + + # Structure + set structure_s [lindex [lindex [lindex [lors::imsmd::mdGeneral -element structure -node $lom -prefix $prefix] 0] 0] 1] + set structure_v [lindex [lindex [lindex [lors::imsmd::mdGeneral -element structure -node $lom -prefix $prefix] 0] 1] 1] + + # Aggregation level + set agg_level_s [lindex [lindex [lindex [lors::imsmd::mdGeneral -element aggregationlevel -node $lom -prefix $prefix] 0] 0] 1] + set agg_level_v [lindex [lindex [lindex [lors::imsmd::mdGeneral -element aggregationlevel -node $lom -prefix $prefix] 0] 1] 1] + + # Catalogentry + set catalogentries [lors::imsmd::mdGeneral -element catalogentry -node $lom -prefix $prefix] + + # Languages + set languages [lors::imsmd::mdGeneral -element language -node $lom -prefix $prefix] + + # Descriptions + set descriptions [lors::imsmd::mdGeneral -element description -node $lom -prefix $prefix] + + # Keywords + set keywords [lors::imsmd::mdGeneral -element keyword -node $lom -prefix $prefix] + + # Coverages + set coverages [lors::imsmd::mdGeneral -element coverage -node $lom -prefix $prefix] + + # Now we insert the values into the DB + db_dml add_new_general { + insert into ims_md_general (ims_md_id, structure_s, structure_v, agg_level_s, agg_level_v) + values + (:p_ims_md_id, :structure_s, :structure_v, :agg_level_s, :agg_level_v) + } + + + # Adds General Titles + + foreach title $titles { + set p_ims_md_ge_ti_id [db_nextval ims_md_general_title_seq] + set p_title_l [lindex $title 0] + set p_title_s [lindex $title 1] + + db_dml add_new_general_titles { + insert into ims_md_general_title (ims_md_ge_ti_id, ims_md_id, title_l, title_s) + values + (:p_ims_md_ge_ti_id, :p_ims_md_id, :p_title_l, :p_title_s) + } + + } + + # Adds General Catalog Entries + foreach catalogentry $catalogentries { + set p_ims_md_ge_cata_id [db_nextval ims_md_general_cata_seq] + set p_catalog [lindex $catalogentry 0] + set p_entry_l [lindex [lindex $catalogentry 1] 0] + set p_entry_s [lindex [lindex $catalogentry 1] 1] + + db_dml add_new_general_catalogentries { + + insert into ims_md_general_cata (ims_md_ge_cata_id, ims_md_id, catalog, entry_l, entry_s) + values + (:p_ims_md_ge_cata_id, :p_ims_md_id, :p_catalog, :p_entry_l, :p_entry_s) + } + } + + # Adds General Languages + foreach language $languages { + set p_ims_md_ge_lang_id [db_nextval ims_md_general_lang_seq] + + db_dml add_new_general_language { + insert into ims_md_general_lang (ims_md_ge_lang_id, ims_md_id, language) + values + (:p_ims_md_ge_lang_id, :p_ims_md_id, :language) + } + } + + # Adds General Description + foreach description $descriptions { + set p_ims_md_ge_desc_id [db_nextval ims_md_general_desc_seq] + set p_descrip_l [lindex $description 0] + set p_descrip_s [lindex $description 1] + + db_dml add_new_general_description { + insert into ims_md_general_desc (ims_md_ge_desc_id, ims_md_id, descrip_l, descrip_s) + values + (:p_ims_md_ge_desc_id, :p_ims_md_id, :p_descrip_l, :p_descrip_s) + } + } + + # Adds General Keywords + foreach keyword $keywords { + set p_ims_md_ge_key_id [db_nextval ims_md_general_key_seq] + set p_keyword_l [lindex $keyword 0] + set p_keyword_s [lindex $keyword 1] + + db_dml add_new_general_keyword { + insert into ims_md_general_key (ims_md_ge_key_id, ims_md_id, keyword_l, keyword_s) + values + (:p_ims_md_ge_key_id, :p_ims_md_id, :p_keyword_l, :p_keyword_s) + } + } + + # Adds General Coverage + foreach coverage $coverages { + set p_ims_md_ge_cove_id [db_nextval ims_md_general_cover_seq] + set p_cover_l [lindex $coverage 0] + set p_cover_s [lindex $coverage 1] + + db_dml add_new_general_coverage { + insert into ims_md_general_cover (ims_md_ge_cove_id, ims_md_id, cover_l, cover_s) + values + (:p_ims_md_ge_cove_id, :p_ims_md_id, :p_cover_l, :p_cover_s) + } + } + + # Lifecycle + + # Version + set version [lors::imsmd::mdLifeCycle -element version -node $lom -prefix $prefix] + set version_l [lindex [lindex $version 0] 0] + set version_s [lindex [lindex $version 0] 1] + + # Status + set status [lors::imsmd::mdLifeCycle -element status -node $lom -prefix $prefix] + set status_s [lindex [lindex [lindex $status 0] 0] 1] + set status_v [lindex [lindex [lindex $status 0] 1] 1] + + # Contribute + set contributes [lors::imsmd::mdLifeCycle -element contribute -node $lom -prefix $prefix] + + # Adds Lifecycle Version and Status + db_dml add_new_lifecycle { + insert into ims_md_life_cycle (ims_md_id, version_l, version_s, status_s, status_v) + values + (:p_ims_md_id, :version_l, :version_s, :status_s, :status_v) + } + + # Adds Lifecycle Contributes + foreach contribute $contributes { + set p_ims_md_lf_cont_id [db_nextval ims_md_life_cycle_contrib_seq] + set p_role_s [lindex [lindex [lindex $contribute 0] 0] 1] + set p_role_v [lindex [lindex [lindex $contribute 0] 1] 1] + set p_cont_date [lindex [lindex $contribute 2] 0] + set p_cont_date_l [lindex [lindex [lindex $contribute 2] 1] 0] + set p_cont_date_s [lindex [lindex [lindex $contribute 2] 1] 1] + + set p_entities [lindex $contribute 1] + + db_dml add_new_lifecycle_contrib { + insert into ims_md_life_cycle_contrib (ims_md_lf_cont_id, ims_md_id, role_s, role_v, cont_date, cont_date_l, cont_date_s) + values + (:p_ims_md_lf_cont_id, :p_ims_md_id, :p_role_s, :p_role_v, :p_cont_date, :p_cont_date_l, :p_cont_date_s) + } + + + foreach entity $p_entities { + set p_ims_md_lf_cont_enti_id [db_nextval ims_md_life_cycle_contrib_entity_seq] + set p_entity $entity + + db_dml add_new_lifecycle_contrib_entity { + insert into ims_md_life_cycle_contrib_entity (ims_md_lf_cont_enti_id, ims_md_lf_cont_id, entity) + values + (:p_ims_md_lf_cont_enti_id, :p_ims_md_lf_cont_id, :p_entity) + } + } + + } + + # Metadata + + # Language + set p_language [lors::imsmd::mdMetadata -element language -node $lom -prefix $prefix] + + # Catalogentry + set catalogentries [lors::imsmd::mdMetadata -element catalogentry -node $lom -prefix $prefix] + + # Contribute + set contributes [lors::imsmd::mdMetadata -element contribute -node $lom -prefix $prefix] + + # Metadatascheme + set metadataschemes [lors::imsmd::mdMetadata -element metadatascheme -node $lom -prefix $prefix] + + # Adds Metadata Language + db_dml add_new_metadata { + insert into ims_md_metadata (ims_md_id, language) + values + (:p_ims_md_id, :p_language) + } + + # Adds Catalogentry + foreach catalogentry $catalogentries { + set p_ims_md_md_cata_id [db_nextval ims_md_metadata_cata_seq] + set p_catalog [lindex $catalogentry 0] + set p_entry_l [lindex [lindex $catalogentry 1] 0] + set p_entry_s [lindex [lindex $catalogentry 1] 1] + + db_dml add_new_metadata_catalogentries { + insert into ims_md_metadata_cata (ims_md_md_cata_id, ims_md_id, catalog, entry_l, entry_s) + values + (:p_ims_md_md_cata_id, :p_ims_md_id, :p_catalog, :p_entry_l, :p_entry_s) + } + } + + # Adds Lifecycle Contributes + foreach contribute $contributes { + set p_ims_md_md_cont_id [db_nextval ims_md_metadata_contrib_seq] + set p_role_s [lindex [lindex [lindex $contribute 0] 0] 1] + set p_role_v [lindex [lindex [lindex $contribute 0] 1] 1] + set p_cont_date [lindex [lindex $contribute 2] 0] + set p_cont_date_l [lindex [lindex [lindex $contribute 2] 1] 0] + set p_cont_date_s [lindex [lindex [lindex $contribute 2] 1] 1] + + set p_ims_md_md_cont_enti_id [db_nextval ims_md_metadata_contrib_entity_seq] + set p_entity [lindex [lindex $contribute 1] 0] + + db_dml add_new_metadata_contrib { + insert into ims_md_metadata_contrib (ims_md_md_cont_id, ims_md_id, role_s, role_v, cont_date, cont_date_l, cont_date_s) + values + (:p_ims_md_md_cont_id, :p_ims_md_id, :p_role_s, :p_role_v, :p_cont_date, :p_cont_date_l, :p_cont_date_s) + } + + db_dml add_new_metadata_contrib_entity { + insert into ims_md_metadata_contrib_entity (ims_md_md_cont_enti_id, ims_md_md_cont_id, entity) + values + (:p_ims_md_md_cont_enti_id, :p_ims_md_md_cont_id, :p_entity) + } + + } + + # Adds Metadata Schemes + foreach metadatascheme $metadataschemes { + set p_scheme $metadatascheme + + db_dml add_new_metadata_metadatascheme { + insert into ims_md_metadata_scheme (ims_md_id, scheme) + values + (:p_ims_md_id, :p_scheme) + } + } + + # Technical + + # format + set formats [lors::imsmd::mdTechnical -element format -node $lom -prefix $prefix] + + # location + set locations [lors::imsmd::mdTechnical -element location -node $lom -prefix $prefix] + + # size, installation remarks, otherplatformrequirements, duration + set p_size [lors::imsmd::mdTechnical -element size -node $lom -prefix $prefix] + set p_instl_rmks [lors::imsmd::mdTechnical -element installationremarks -node $lom -prefix $prefix] + set p_instl_rmks_l [lindex [lindex $p_instl_rmks 0] 0] + set p_instl_rmks_s [lindex [lindex $p_instl_rmks 0] 1] + set p_otr_plt [lors::imsmd::mdTechnical -element otherplatformrequirements -node $lom -prefix $prefix] + set p_otr_plt_l [lindex [lindex $p_otr_plt 0] 0] + set p_otr_plt_s [lindex [lindex $p_otr_plt 0] 1] + set p_durat [lors::imsmd::mdTechnical -element duration -node $lom -prefix $prefix] + set p_duration [lindex $p_durat 0] + set p_duration_l [lindex [lindex $p_durat 1] 0] + set p_duration_s [lindex [lindex $p_durat 1] 1] + + # requirement + set requirements [lors::imsmd::mdTechnical -element requirement -node $lom -prefix $prefix] + + # Adds Technical size, installation remarks, otherplatformrequirements, duration + db_dml add_new_technical { + insert into ims_md_technical (ims_md_id, t_size, instl_rmrks_l, instl_rmrks_s, otr_plt_l, otr_plt_s, duration, duration_l, duration_s) + values + (:p_ims_md_id, :p_size, :p_instl_rmks_l, :p_instl_rmks_s, :p_otr_plt_l, :p_otr_plt_s, :p_duration, :p_duration_l, :p_duration_s) + } + + # Adds Technical Format + + foreach format $formats { + set p_ims_md_te_fo_id [db_nextval ims_md_technical_format_seq] + set p_format $format + + db_dml add_new_technical_format { + insert into ims_md_technical_format (ims_md_te_fo_id, ims_md_id, format) + values + (:p_ims_md_te_fo_id, :p_ims_md_id, :p_format) + } + } + + # Adds Technical Location + + foreach location $locations { + set p_ims_md_te_lo_id [db_nextval ims_md_technical_location_seq] + set p_type [lindex $location 1] + set p_location [lindex $location 0] + + db_dml add_new_technical_location { + insert into ims_md_technical_location (ims_md_te_lo_id, ims_md_id, type, location) + values + (:p_ims_md_te_lo_id, :p_ims_md_id, :p_type, :p_location) + } + } + + # Adds Technical Requirements + + foreach requirement $requirements { + set p_ims_md_te_rq_id [db_nextval ims_md_technical_requirement_seq] + set p_type_s [lindex [lindex [lindex $requirement 0] 0] 1] + set p_type_v [lindex [lindex [lindex $requirement 0] 1] 1] + set p_name_s [lindex [lindex [lindex $requirement 1] 0] 1] + set p_name_v [lindex [lindex [lindex $requirement 1] 1] 1] + set p_min_version [lindex $requirement 2] + set p_max_version [lindex $requirement 3] + + db_dml add_new_technical_requirement { + insert into ims_md_technical_requirement (ims_md_te_rq_id, ims_md_id, type_s, type_v, name_s, name_v, min_version, max_version) + values + (:p_ims_md_te_rq_id, :p_ims_md_id, :p_type_s, :p_type_v, :p_name_s, :p_name_v, :p_min_version, :p_max_version) + } + } + + + # Educational + + # interactivitytype, interactivitylevel, semanticdensity, difficulty, typical_learning_time, description + set p_int_type [lors::imsmd::mdEducational -element interactivitytype -node $lom -prefix $prefix] + set p_int_type_s [lindex [lindex [lindex $p_int_type 0] 0] 1] + set p_int_type_v [lindex [lindex [lindex $p_int_type 0] 1] 1] + set p_int_level [lors::imsmd::mdEducational -element interactivitylevel -node $lom -prefix $prefix] + set p_int_level_s [lindex [lindex [lindex $p_int_level 0] 0] 1] + set p_int_level_v [lindex [lindex [lindex $p_int_level 0] 1] 1] + set p_sem_density [lors::imsmd::mdEducational -element semanticdensity -node $lom -prefix $prefix] + set p_sem_density_s [lindex [lindex [lindex $p_sem_density 0] 0] 1] + set p_sem_density_v [lindex [lindex [lindex $p_sem_density 0] 1] 1] + set p_difficulty [lors::imsmd::mdEducational -element difficulty -node $lom -prefix $prefix] + set p_difficulty_s [lindex [lindex [lindex $p_difficulty 0] 0] 1] + set p_difficulty_v [lindex [lindex [lindex $p_difficulty 0] 1] 1] + set p_type_lrn_tim [lors::imsmd::mdEducational -element typicallearningtime -node $lom -prefix $prefix] + set p_type_lrn_time [lindex $p_type_lrn_tim 0] + set p_type_lrn_time_l [lindex [lindex $p_type_lrn_tim 1] 0] + set p_type_lrn_time_s [lindex [lindex $p_type_lrn_tim 1] 1] + set descrips [lors::imsmd::mdEducational -element description -node $lom -prefix $prefix] + + # learningresourcetype + set learningresourcetypes [lors::imsmd::mdEducational -element learningresourcetype -node $lom -prefix $prefix] + + + # intendedenduserrole + set intendedenduserroles [lors::imsmd::mdEducational -element intendedenduserrole -node $lom -prefix $prefix] + + # context + set contexts [lors::imsmd::mdEducational -element context -node $lom -prefix $prefix] + + # typicalagerange + set typicalageranges [lors::imsmd::mdEducational -element typicalagerange -node $lom -prefix $prefix] + + # language + set languages [lors::imsmd::mdEducational -element language -node $lom -prefix $prefix] + + + # Adds Educational interactivitytype, interactivitylevel, semanticdensity, difficulty, typical_learning_time + db_dml add_new_educational { + insert into ims_md_educational (ims_md_id, int_type_s, int_type_v, int_level_s, int_level_v, sem_density_s, sem_density_v, difficulty_s, difficulty_v, type_lrn_time, type_lrn_time_l, type_lrn_time_s) + values + (:p_ims_md_id, :p_int_type_s, :p_int_type_v, :p_int_level_s, :p_int_level_v, :p_sem_density_s, :p_sem_density_v, :p_difficulty_s, :p_difficulty_v, :p_type_lrn_time, :p_type_lrn_time_l, :p_type_lrn_time_s) + } + + # Adds descriptions + foreach descrip $descrips { + set p_ims_md_ed_de_id [db_nextval ims_md_educational_descrip_seq] + set p_descrip_l [lindex $descrip 0] + set p_descrip_s [lindex $descrip 1] + + db_dml add_new_descriptions { + insert into ims_md_educational_descrip (ims_md_ed_de_id, ims_md_id, descrip_l, descrip_s) + values + (:p_ims_md_ed_de_id, :p_ims_md_id, :p_descrip_l, :p_descrip_s) + } + } + + # Adds learningresourcetype + foreach lrt $learningresourcetypes { + set p_ims_md_ed_lr_id [db_nextval ims_md_educational_lrt_seq] + set p_lrt_s [lindex [lindex $lrt 0] 1] + set p_lrt_v [lindex [lindex $lrt 1] 1] + + db_dml add_new_learningresourcetypes { + insert into ims_md_educational_lrt (ims_md_ed_lr_id, ims_md_id, lrt_s, lrt_v) + values + (:p_ims_md_ed_lr_id, :p_ims_md_id, :p_lrt_s, :p_lrt_v) + } + } + + # Adds intendedenduserrole + foreach ieur $intendedenduserroles { + set p_ims_md_ed_ie_id [db_nextval ims_md_educational_ieur_seq] + set p_ieur_s [lindex [lindex $ieur 0] 1] + set p_ieur_v [lindex [lindex $ieur 1] 1] + + db_dml add_new_intendedenduserroles { + insert into ims_md_educational_ieur (ims_md_ed_ie_id, ims_md_id, ieur_s, ieur_v) + values + (:p_ims_md_ed_ie_id, :p_ims_md_id, :p_ieur_s, :p_ieur_v) + } + } + + # Adds context + foreach context $contexts { + set p_ims_md_ed_co_id [db_nextval ims_md_educational_context_seq] + set p_context_s [lindex [lindex $context 0] 1] + set p_context_v [lindex [lindex $context 1] 1] + + db_dml add_new_context { + insert into ims_md_educational_context (ims_md_ed_co_id, ims_md_id, context_s, context_v) + values + (:p_ims_md_ed_co_id, :p_ims_md_id, :p_context_s, :p_context_v) + } + } + + # Adds typicalagerange + foreach tar $typicalageranges { + set p_ims_md_ed_ta_id [db_nextval ims_md_educational_tar_seq] + set p_tar_l [lindex $tar 0] + set p_tar_s [lindex $tar 1] + + db_dml add_new_typicalagerange { + insert into ims_md_educational_tar (ims_md_ed_ta_id, ims_md_id, tar_l, tar_s) + values + (:p_ims_md_ed_ta_id, :p_ims_md_id, :p_tar_l, :p_tar_s) + } + } + + # Adds Languages + foreach lang $languages { + set p_ims_md_ed_la_id [db_nextval ims_md_educational_lang_seq] + set p_language $lang + + db_dml add_new_language { + insert into ims_md_educational_lang (ims_md_ed_la_id, ims_md_id, language) + values + (:p_ims_md_ed_la_id, :p_ims_md_id, :p_language) + } + } + + # Rights + # cost, copyrightsandotherrights, description + set p_cost [lors::imsmd::mdRights -element cost -node $lom -prefix $prefix] + set p_caor [lors::imsmd::mdRights -element copyrightandotherrestrictions -node $lom -prefix $prefix] + set p_descrip [lors::imsmd::mdRights -element description -node $lom -prefix $prefix] + + set p_cost_s [lindex [lindex [lindex $p_cost 0] 0] 1] + set p_cost_v [lindex [lindex [lindex $p_cost 0] 1] 1] + + set p_caor_s [lindex [lindex [lindex $p_caor 0] 0] 1] + set p_caor_v [lindex [lindex [lindex $p_caor 0] 1] 1] + + set p_descrip_l [lindex [lindex $p_descrip 0] 0] + set p_descrip_s [lindex [lindex $p_descrip 0] 1] + + db_dml add_new_rights { + insert into ims_md_rights (ims_md_id, cost_s, cost_v, caor_s, caor_v, descrip_l, descrip_s) + values + (:p_ims_md_id, :p_cost_s, :p_cost_v, :p_caor_s, :p_caor_v, :p_descrip_l, :p_descrip_s) + } + + # Relation + + # Relation returns all in one large list + set relations [lors::imsmd::mdRelation -node $lom -prefix $prefix] + + foreach relation $relations { + + set p_ims_md_re_id [db_nextval ims_md_relation_seq] + set p_kind_s [lindex [lindex [lindex [lindex $relation 0] 0] 0] 1] + set p_kind_v [lindex [lindex [lindex [lindex $relation 0] 0] 1] 1] + + # Adds kind + db_dml add_new_relation { + insert into ims_md_relation (ims_md_re_id, ims_md_id, kind_s, kind_v) + values + (:p_ims_md_re_id, :p_ims_md_id, :p_kind_s, :p_kind_v) + } + + set p_ims_md_re_re_id [db_nextval ims_md_relation_resource_seq] + set p_descrip_l [lindex [lindex [lindex $relation 1] 0] 0] + set p_descrip_s [lindex [lindex [lindex $relation 1] 0] 1] + + # adds description to resource + db_dml add_new_relation_descrip { + insert into ims_md_relation_resource (ims_md_re_re_id, ims_md_re_id, identifier, descrip_l, descrip_s) + values + (:p_ims_md_re_re_id, :p_ims_md_re_id, null, :p_descrip_l, :p_descrip_s) + } + + # catalogentries + set catalogentries [lindex $relation 2] + + # adds catalogentries + foreach catalogentry $catalogentries { + + set p_ims_md_re_re_ca_id [db_nextval ims_md_relation_resource_catalog_seq] + set p_catalog [lindex $catalogentry 0] + set p_entry_l [lindex [lindex $catalogentry 1] 0] + set p_entry_s [lindex [lindex $catalogentry 1] 1] + + db_dml add_new_catalogentry { + + insert into ims_md_relation_resource_catalog (ims_md_re_re_ca_id, ims_md_re_re_id, catalog, entry_l, entry_s) + values + (:p_ims_md_re_re_ca_id, :p_ims_md_re_re_id, :p_catalog, :p_entry_l, :p_entry_s) + } + } + + } + + # Annotation + + set annotations [lors::imsmd::mdAnnotation -node $lom -prefix $prefix] + + foreach annotation $annotations { + set p_ims_md_an_id [db_nextval ims_md_annotation_seq] + set p_entity [lindex [lindex $annotation 0] 0] + set p_date [lindex [lindex $annotation 1] 0] + set p_date_l [lindex [lindex [lindex $annotation 1] 1] 0] + set p_date_s [lindex [lindex [lindex $annotation 1] 1] 1] + + set p_descriptions [lindex $annotation 2] + + db_dml add_new_annotation { + insert into ims_md_annotation (ims_md_an_id, ims_md_id, entity, date, date_l, date_s) + values + (:p_ims_md_an_id, :p_ims_md_id, :p_entity, :p_date, :p_date_l, :p_date_s) + } + + foreach description $p_descriptions { + + set p_ims_md_an_de_id [db_nextval ims_md_annotation_descrip_seq] + set p_descrip_l [lindex $description 0] + set p_descrip_s [lindex $description 1] + + db_dml add_new_ann_descriptions { + insert into ims_md_annotation_descrip (ims_md_an_de_id, ims_md_an_id, descrip_l, descrip_s) + values + (:p_ims_md_an_de_id, :p_ims_md_an_id, :p_descrip_l, :p_descrip_s) + } + + } + + + } + + # Classification + + set classifications [lors::imsmd::mdClassification -node $lom -prefix $prefix] + + foreach class $classifications { + + # purpose + set p_ims_md_cl_id [db_nextval ims_md_classification_seq] + set p_purpose_s [lindex [lindex [lindex [lindex [lindex $class 0] 0] 0] 0] 1] + set p_purpose_v [lindex [lindex [lindex [lindex [lindex $class 0] 0] 0] 1] 1] + + db_dml add_new_classification { + insert into ims_md_classification (ims_md_cl_id, ims_md_id, purpose_s, purpose_v) + values + (:p_ims_md_cl_id, :p_ims_md_id, :p_purpose_s, :p_purpose_v) + } + + # description + set descriptions [lindex [lindex $class 0] 1] + + foreach desc $descriptions { + set p_ims_md_cl_de_id [db_nextval ims_md_classification_desc_seq] + set p_descrip_l [lindex $desc 0] + set p_descrip_s [lindex $desc 1] + + db_dml add_new_description { + insert into ims_md_classification_descrip (ims_md_cl_de_id, ims_md_cl_id, descrip_l, descrip_s) + values + (:p_ims_md_cl_de_id, :p_ims_md_cl_id, :p_descrip_l, :p_descrip_s) + } + } + + # taxonpath + set taxonpaths [lindex [lindex $class 0] 2] + + foreach taxonpath $taxonpaths { + + set p_source [lindex $taxonpath 0] + + set p_source_l [lindex [lindex $p_source 0] 0] + set p_source_s [lindex [lindex $p_source 0] 1] + set p_ims_md_cl_ta_id [db_nextval ims_md_classification_taxpath_seq] + + set taxons [lindex $taxonpath 1] + + db_dml add_new_taxonpaths { + insert into ims_md_classification_taxpath (ims_md_cl_ta_id, ims_md_cl_id, source_l, source_v) + values + (:p_ims_md_cl_ta_id, :p_ims_md_cl_id, :p_source_l, :p_source_s) + } + + foreach taxon $taxons { + + set p_ims_md_cl_ta_ta_id [db_nextval ims_md_classification_taxpath_taxon_seq] + set p_hierarchy [lindex $taxon 0] + set p_identifier [lindex $taxon 1] + set p_entry_l [lindex [lindex $taxon 2] 0] + set p_entry_s [lindex [lindex $taxon 2] 1] + + db_dml add_new_taxons { + insert into ims_md_classification_taxpath_taxon (ims_md_cl_ta_ta_id, ims_md_cl_ta_id, hierarchy, identifier, entry_l, entry_s) + values + (:p_ims_md_cl_ta_ta_id, :p_ims_md_cl_ta_id, :p_hierarchy, :p_identifier, :p_entry_l, :p_entry_s) + } + + } + } + + # keywords + set keywords [lindex [lindex $class 0] 3] + + foreach keyword $keywords { + set p_ims_md_cl_ke_id [db_nextval ims_md_classification_keyword_seq] + set p_keyword_l [lindex $keyword 0] + set p_keyword_s [lindex $keyword 1] + + db_dml add_new_keywords { + insert into ims_md_classification_keyword (ims_md_cl_ke_id, ims_md_cl_id, keyword_l, keyword_s) + values + (:p_ims_md_cl_ke_id, :p_ims_md_cl_id, :p_keyword_l, :p_keyword_s) + } + } + } + } + } + return 1 + } + + +} \ No newline at end of file