Ernie Ghiglione
-
-
+ IMS Content Packaging and Medata Services.
+Implementation of IMS CP and MD for .LRN
+ 2004-08-06
+ This is a service and library to manage IMS Content Packaging and Metadata. From version 0.4d onward it supports SCORM and Blackboard imports
+ GPL
+ http://www.gnu.org/copyleft/gpl.html
+ 1
+
+
+
+
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 -r1.1 -r1.2
--- openacs-4/packages/lors/sql/postgresql/lors-create.sql 22 Apr 2004 03:42:06 -0000 1.1
+++ openacs-4/packages/lors/sql/postgresql/lors-create.sql 4 Sep 2004 14:04:07 -0000 1.2
@@ -18,151 +18,6 @@
-- 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(
--
@@ -247,7 +102,9 @@
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
+\i lors-imscp-package-create.sql
+\i lors-imsmd-sc-create.sql
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 -r1.1 -r1.2
--- openacs-4/packages/lors/sql/postgresql/lors-imscp-create.sql 22 Apr 2004 03:42:06 -0000 1.1
+++ openacs-4/packages/lors/sql/postgresql/lors-imscp-create.sql 4 Sep 2004 14:04:07 -0000 1.2
@@ -33,8 +33,8 @@
PERFORM acs_object_type__create_type (
''ims_manifest'', -- object_type
- ''Manifest'', -- pretty_name
- ''Manifests'', -- pretty_plural
+ ''IMS_Manifest'', -- pretty_name
+ ''IMS_Manifests'', -- pretty_plural
''acs_object'', -- supertype
''imscp_manifests'', -- table_name
''man_id'', -- id_column
@@ -45,8 +45,8 @@
);
PERFORM acs_object_type__create_type (
''ims_organization'', -- object_type
- ''Organization'', -- pretty_name
- ''Organizations'', -- pretty_plural
+ ''IMS_Organization'', -- pretty_name
+ ''IMS_Organizations'', -- pretty_plural
''ims_manifest'', -- supertype
''imscp_organizations'', -- table_name
''org_id'', -- id_column
@@ -57,8 +57,8 @@
);
PERFORM acs_object_type__create_type (
''ims_item'', -- object_type
- ''Item'', -- pretty_name
- ''Items'', -- pretty_plural
+ ''IMS_Item'', -- pretty_name
+ ''IMS_Items'', -- pretty_plural
''ims_organization'', -- supertype
''imscp_items'', -- table_name
''item_id'', -- id_column
@@ -69,8 +69,8 @@
);
PERFORM acs_object_type__create_type (
''ims_resource'', -- object_type
- ''Resource'', -- pretty_name
- ''Resources'', -- pretty_plural
+ ''IMS_Resource'', -- pretty_name
+ ''IMS_Resources'', -- pretty_plural
''ims_item'', -- supertype
''imscp_resources'', -- table_name
''org_id'', -- id_column
@@ -100,12 +100,13 @@
identifier varchar(1000),
version varchar(100),
orgs_default varchar(100),
- hasmetadata boolean,
+ hasmetadata boolean default 'f' not null,
-- A manifest could have multiple submanifests
parent_man_id integer,
isscorm boolean,
folder_id integer,
- fs_package_id integer
+ fs_package_id integer,
+ isshared boolean default 'f' not null
);
comment on table ims_cp_manifests is '
@@ -155,7 +156,8 @@
identifier varchar(100),
structure varchar(100),
title varchar(1000),
- hasmetadata boolean
+ hasmetadata boolean default 'f' not null,
+ isshared boolean default 'f' not null
);
-- create index for ims_cp_organizations
@@ -181,15 +183,16 @@
parameters varchar(1000),
title varchar(1000),
parent_item integer,
- hasmetadata boolean,
+ hasmetadata boolean default 'f' not null,
-- 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)
+ masteryscore varchar(255),
+ isshared boolean default 'f' not null
);
-- create index for ims_cp_items
@@ -211,7 +214,7 @@
identifier varchar(1000),
type varchar(1000),
href varchar(2000),
- hasmetadata boolean,
+ hasmetadata boolean default 'f' not null,
-- SCORM specific
scorm_type varchar(1000)
);
@@ -270,10 +273,62 @@
on delete cascade,
pathtofile varchar(2000),
filename varchar(2000),
- hasmetadata boolean,
+ hasmetadata boolean default 'f' not null,
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);
+
+
+create table ims_cp_manifest_class (
+ man_id integer
+ constraint ims_cp_manifest_class__man_id_fk
+ references ims_cp_manifests(man_id)
+ on delete cascade,
+ lorsm_instance_id integer
+ constraint ims_cp_manifest_class__lorsm_fk
+ references apm_packages (package_id),
+ community_id integer
+ constraint ims_cp_manifest_class__comm_id_fk
+ references dotlrn_communities_all(community_id),
+ class_key varchar(100)
+ constraint ims_cp_manifest_class__class_key_fk
+ references dotlrn_community_types(community_type),
+ isenabled boolean default 't' not null,
+ istrackable boolean default 'f' not null,
+ primary key (man_id, lorsm_instance_id)
+);
+
+comment on table ims_cp_manifest_class is '
+This table helps us manage the relations between a manifest (course)
+and its .LRN class/community
+';
+
+comment on column ims_cp_manifest_class.man_id is '
+This is the manifest_id for the course
+';
+
+comment on column ims_cp_manifest_class.lorsm_instance_id is '
+This is the package_id for the instance of LORMS in a particular
+.LRN class/community. This is *NOT* the community_id.
+';
+
+comment on column ims_cp_manifest_class.community_id is '
+This is the package_id for the class/community that the manifest got uploaded
+';
+
+comment on column ims_cp_manifest_class.class_key is '
+This is the class_key for the class/community
+';
+
+comment on column ims_cp_manifest_class.isenabled is '
+Whether the course is enabled for that community instance.
+default true
+';
+
+comment on column ims_cp_manifest_class.istrackable is '
+Whether the course is trackable for that community instance.
+default false
+';
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 -r1.1 -r1.2
--- openacs-4/packages/lors/sql/postgresql/lors-imscp-package-create.sql 22 Apr 2004 03:42:06 -0000 1.1
+++ openacs-4/packages/lors/sql/postgresql/lors-imscp-package-create.sql 4 Sep 2004 14:04:07 -0000 1.2
@@ -36,7 +36,9 @@
timestamp with time zone, -- creation_date
integer, -- creation_user
varchar, -- creation_ip
- integer -- package_id
+ integer, -- package_id
+ integer, -- community_id
+ varchar -- class_key
)
returns integer as '
declare
@@ -49,11 +51,13 @@
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_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;
+ p_community_id alias for $15;
+ p_class_key alias for $16;
v_man_id integer;
begin
@@ -72,6 +76,14 @@
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);
+ -- now we add it to the manifest_class relation table
+
+ insert into ims_cp_manifest_class
+ (man_id, lorsm_instance_id, community_id, class_key, isenabled, istrackable)
+ values
+ (v_man_id, p_package_id, p_community_id, p_class_key, ''t'', ''f'');
+
+
return v_man_id;
end;
' language 'plpgsql';
@@ -373,4 +385,34 @@
return p_file_id;
end;
-' language 'plpgsql';
\ No newline at end of file
+' language 'plpgsql';
+
+
+-- put in and correct some stuff for ims_cp_items
+
+-- function name
+create or replace function ims_item__name (integer)
+returns varchar as '
+declare
+ name__object_id alias for $1;
+ v_title ims_cp_items.title%TYPE;
+ v_object_id integer;
+begin
+
+ select title
+ into v_title
+ from ims_cp_items
+ where item_id = name__object_id;
+
+ return v_title;
+
+end;' language 'plpgsql' stable strict;
+
+
+update acs_object_types
+set table_name = 'ims_cp_items',
+ name_method = 'ims_item__name',
+ pretty_name = 'IMS Item',
+ pretty_plural = 'IMS Items'
+where object_type = 'ims_item';
+
Index: openacs-4/packages/lors/sql/postgresql/lors-imsmd-sc-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/lors/sql/postgresql/lors-imsmd-sc-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/lors/sql/postgresql/lors-imsmd-sc-create.sql 4 Sep 2004 14:04:07 -0000 1.1
@@ -0,0 +1,163 @@
+-- This is LORS IMS Metadata implementation of the FtsContentProvider
+-- service contract
+
+
+-- for manifests metadata
+
+select acs_sc_impl__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_manifest', -- impl_name
+ 'lors' -- impl_owner_name
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_manifest', -- impl_name
+ 'datasource', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__datasource', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_manifest', -- impl_name
+ 'url', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__url', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+
+create function ims_md_record__itrg ()
+returns opaque as '
+begin
+ perform search_observer__enqueue(new.ims_md_id,''INSERT'');
+ return null;
+end;' language 'plpgsql';
+
+create function ims_md_record__dtrg ()
+returns opaque as '
+begin
+ perform search_observer__enqueue(old.ims_md_id,''DELETE'');
+ return old;
+end;' language 'plpgsql';
+
+create function ims_md_record__utrg ()
+returns opaque as '
+begin
+ perform search_observer__enqueue(old.ims_md_id,''DELETE'');
+ perform search_observer__enqueue(old.ims_md_id,''UPDATE'');
+ return old;
+end;' language 'plpgsql';
+
+
+create trigger lors_imsmd__itrg after insert on ims_md
+for each row execute procedure ims_md_record__itrg ();
+
+create trigger lors_imsmd__dtrg after delete on ims_md
+for each row execute procedure ims_md_record__dtrg ();
+
+create trigger pinds_blog_entries__utrg after update on ims_md
+for each row execute procedure ims_md_record__utrg ();
+
+-- Add the binding
+
+select acs_sc_binding__new (
+ 'FtsContentProvider',
+ 'ims_manifest'
+);
+
+
+-- for organization's metadata
+
+select acs_sc_impl__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_organization', -- impl_name
+ 'lors' -- impl_owner_name
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_organization', -- impl_name
+ 'datasource', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__datasource', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_organization', -- impl_name
+ 'url', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__url', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+-- Add the binding
+
+select acs_sc_binding__new (
+ 'FtsContentProvider',
+ 'ims_organization'
+);
+
+
+-- for item's metadata
+
+select acs_sc_impl__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_item', -- impl_name
+ 'lors' -- impl_owner_name
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_item', -- impl_name
+ 'datasource', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__datasource', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_item', -- impl_name
+ 'url', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__url', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+-- Add the binding
+
+select acs_sc_binding__new (
+ 'FtsContentProvider',
+ 'ims_item'
+);
+
+
+-- for resource's metadata
+
+select acs_sc_impl__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_resource', -- impl_name
+ 'lors' -- impl_owner_name
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_resource', -- impl_name
+ 'datasource', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__datasource', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+select acs_sc_impl_alias__new(
+ 'FtsContentProvider', -- impl_contract_name
+ 'ims_resource', -- impl_name
+ 'url', -- impl_operation_name
+ 'lors::imsmd::sc::mdrecord__url', -- impl_alias
+ 'TCL' -- impl_pl
+);
+
+-- Add the binding
+
+select acs_sc_binding__new (
+ 'FtsContentProvider',
+ 'ims_resource'
+);
Index: openacs-4/packages/lors/tcl/lors-imscp-blackboard6-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/lors/tcl/lors-imscp-blackboard6-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/lors/tcl/lors-imscp-blackboard6-procs.tcl 4 Sep 2004 14:04:08 -0000 1.1
@@ -0,0 +1,1029 @@
+ad_library {
+
+ IMS Content Packaging functions
+ for Blackboard 6
+
+ @creation-date 2003-10-13
+ @author Ernie Ghiglione (ErnieG@mm.st)
+ @cvs-id $Id: lors-imscp-blackboard6-procs.tcl,v 1.1 2004/09/04 14:04: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::imscp::bb6 {}
+
+ad_proc -public lors::imscp::bb6::isBlackboard6 {
+ -tmp_dir:required
+} {
+ Checks whether the IMS CP package is a a Blackboard 6 package (or
+ has Blackboard6 extensions)
+
+ Blackboard6 exports add a .bb-package-info file that contain
+ technical details of the Blackboard installation. Therefore, we
+ will check if the package comes with this file. If it does. we
+ return 1, otherwise 0.
+
+ @param tmp_dir temporary directory
+ @author Ernie Ghiglione (ErnieG@mm.st)
+
+} {
+ return [file exists $tmp_dir/.bb-package-info]
+}
+
+
+ad_proc -public lors::imscp::bb6::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
+ }
+
+ set it_list ""
+ foreach itemx [$tree child all item] {
+
+ set cc ""
+ #{$parent}"
+ # gets item identifier
+ set cc "[lors::imsmd::getAtt $itemx identifier]"
+
+ # gets item identifierref
+ set cc [concat $cc "[lors::imsmd::getAtt $itemx identifierref]"]
+
+ # gets xml node
+ set cc [concat $cc $itemx]
+
+ set it_list [concat $it_list [list $cc]]
+
+ set itemxx [$itemx child all item]
+ if { ![empty_string_p $itemxx] } {
+ set it_list [concat $it_list [getItems $itemx]]
+ }
+ set items [concat $items $cc]
+ }
+ }
+ return $it_list
+ #$items
+}
+
+
+ad_proc -public lors::imscp::bb6::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::bb6::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::bb6::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::bb6::content_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::bb6::content_getItemAttributes {
+ -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::bb6::get_coursetoc {
+ -file:required
+} {
+ Gets content from Blackboard's course/x-bb-coursetoc elements
+
+ @option file filename
+ @author Ernie Ghiglione (ErnieG@mm.st)
+} {
+
+ # set utf-8 system encoding
+ encoding system utf-8
+
+ # open xml file
+ set doc [dom parse [read [open $file]]]
+ # coursetoc
+ set coursetoc [$doc documentElement]
+
+ set list_items [list]
+
+ # gets coursetoc elements and values
+ lappend list_items {id} [lors::imsmd::getAtt $coursetoc id]
+ lappend list_items {LABEL} [lors::imsmd::getAtt [$coursetoc getElementsByTagName LABEL] value]
+ lappend list_items {URL} [lors::imsmd::getAtt [$coursetoc getElementsByTagName URL] value]
+ lappend list_items {TARGETTYPE} [lors::imsmd::getAtt [$coursetoc getElementsByTagName TARGETTYPE] value]
+ lappend list_items {INTERNALHANDLE} [lors::imsmd::getAtt [$coursetoc getElementsByTagName INTERNALHANDLE ] value]
+ lappend list_items {LAUNCHINNEWWINDOW} [lors::imsmd::getAtt [$coursetoc getElementsByTagName LAUNCHINNEWWINDOW] value]
+ lappend list_items {ISENABLED} [lors::imsmd::getAtt [$coursetoc getElementsByTagName ISENABLED] value]
+ lappend list_items {ISENTYRPOINT} [lors::imsmd::getAtt [$coursetoc getElementsByTagName ISENTYRPOINT] value]
+ lappend list_items {ALLOWOBSERVERS} [lors::imsmd::getAtt [$coursetoc getElementsByTagName ALLOWOBSERVERS] value]
+ lappend list_items {ALLOWGUESTS} [lors::imsmd::getAtt [$coursetoc getElementsByTagName ALLOWGUESTS] value]
+
+ # deletes the dom
+ $doc delete
+
+ # return list
+ return $list_items
+
+}
+
+
+ad_proc -public lors::imscp::bb6::get_bb_doc {
+ -file:required
+} {
+ Gets content from Blackboard's resource/x-bb-documen elements
+
+ @option file filename
+ @author Ernie Ghiglione (ErnieG@mm.st)
+} {
+
+ # set utf-8 system encoding
+ encoding system utf-8
+
+ # open xml file
+ set doc [dom parse [read [open $file]]]
+ # content
+ set content [$doc documentElement]
+
+ set list_items [list]
+
+ # gets content elements and values
+ lappend list_items {id} [lors::imsmd::getAtt $content id]
+ lappend list_items {TITLE} [lors::imsmd::getAtt [$content getElementsByTagName TITLE] value]
+ lappend list_items {TITLECOLOR} [lors::imsmd::getAtt [$content getElementsByTagName TITLECOLOR] value]
+ lappend list_items {TEXT} [lors::imsmd::getElement [$content getElementsByTagName TEXT]]
+ lappend list_items {TYPE} [lors::imsmd::getAtt [$content getElementsByTagName TYPE] value]
+ lappend list_items {CREATED} [lors::imsmd::getAtt [$content selectNodes /CONTENT/DATES/CREATED] value]
+ lappend list_items {UPDATED} [lors::imsmd::getAtt [$content selectNodes /CONTENT/DATES/UPDATED] value]
+ lappend list_items {START} [lors::imsmd::getAtt [$content getElementsByTagName START] value]
+ lappend list_items {ISAVAILABLE} [lors::imsmd::getAtt [$content getElementsByTagName ISAVAILABLE] value]
+ lappend list_items {ISFROMCARTRIDGE} [lors::imsmd::getAtt [$content getElementsByTagName ISFROMCARTRIDGE] value]
+ lappend list_items {ISFOLDER} [lors::imsmd::getAtt [$content getElementsByTagName ISFOLDER] value]
+ lappend list_items {ISDESCRIBED} [lors::imsmd::getAtt [$content getElementsByTagName ISDESCRIBED] value]
+ lappend list_items {ISTRACKED} [lors::imsmd::getAtt [$content getElementsByTagName ISTRACKED] value]
+ lappend list_items {ISLESSON} [lors::imsmd::getAtt [$content getElementsByTagName ISLESSON] value]
+ lappend list_items {ISSEQUENTIAL} [lors::imsmd::getAtt [$content getElementsByTagName ISSEQUENTIAL] value]
+ lappend list_items {ALLOWGUESTS} [lors::imsmd::getAtt [$content getElementsByTagName ALLOWGUESTS] value]
+ lappend list_items {ALLOWOBSERVERS} [lors::imsmd::getAtt [$content getElementsByTagName ALLOWOBSERVERS] value]
+ lappend list_items {LAUNCHINNEWWINDOW} [lors::imsmd::getAtt [$content getElementsByTagName LAUNCHINNEWWINDOW] value]
+ lappend list_items {CONTENTHANDLER} [lors::imsmd::getAtt [$content getElementsByTagName CONTENTHANDLER] value]
+ lappend list_items {RENDERTYPE} [lors::imsmd::getAtt [$content getElementsByTagName RENDERTYPE] value]
+ lappend list_items {URL} [lors::imsmd::getAtt [$content getElementsByTagName URL] value]
+
+ set files [list]
+ foreach file [[$content selectNodes /CONTENT/FILES] childNodes] {
+
+ set file_list [list]
+ lappend file_list {file_id} [lors::imsmd::getAtt $file id]
+ lappend file_list {NAME} [lors::imsmd::getElement [$file getElementsByTagName NAME]]
+ lappend file_list {LINKNAME} [lors::imsmd::getAtt [$file getElementsByTagName LINKNAME] value]
+ lappend file_list {SIZE} [lors::imsmd::getAtt [$file getElementsByTagName SIZE] value]
+ lappend file_list {CREATED} [lors::imsmd::getAtt [$file getElementsByTagName CREATED] value]
+ lappend file_list {UPDATED} [lors::imsmd::getAtt [$file getElementsByTagName UPDATED] value]
+
+ lappend files $file_list
+
+ }
+
+ lappend list_items {FILES} $files
+
+ # deletes the dom
+ $doc delete
+
+ # return list
+ return $list_items
+
+}
+
+
+ad_proc -public lors::imscp::bb6::txt_to_html {
+ -txt:required
+ -filename:required
+} {
+ Creates an HTML file from TXT
+
+ @option txt Text to transform into HTML
+ @option filename directory and filename where we are putting the file
+ @author Ernie Ghiglione (ErnieG@mm.st)
+} {
+
+ # set utf-8 system encoding
+ encoding system utf-8
+
+ # get directory info
+ set dirname [file dirname $filename]
+
+ # check if directory exists
+ if { ![file exists $dirname] } {
+ # create dir
+ file mkdir $dirname
+ }
+
+ # transforms text into html
+ if {[lors::imscp::bb6::looks_like_html_p -text $txt]} {
+# set txt [ad_text_to_html -includes_html $txt]
+ } else {
+ set txt [ad_text_to_html -includes_html $txt]
+# set txt [ad_html_text_convert -from "text/plain" -to "text/html" $txt]
+ }
+
+ # saves it on a new html file
+ set f_handler [open $filename w+]
+ fconfigure $f_handler -encoding utf-8
+ puts -nonewline $f_handler " \ $txt \"
+ close $f_handler
+
+ # returns what is is an href for resources
+ return $filename
+
+}
+
+
+ad_proc -public lors::imscp::bb6::looks_like_html_p {
+ -text:required
+} {
+ Creates an HTML file from TXT.
+ This one expands ad_looks_like_html_p
+
+ @param txt text to check for html tags
+ @return 1 if it looks like html, 0 if not.
+ @author Ernie Ghiglione (ErnieG@mm.st)
+} {
+
+ if { [regexp -nocase {} $text] || [regexp -nocase {
} $text] || [regexp -nocase {} $text] || [regexp -nocase {