Skip to content

Commit

Permalink
LSNBLDR-311 - Support for IMS CP import for Lessons (sakaiproject#4210)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonespm authored Apr 14, 2017
1 parent 9f1672a commit 03caa06
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 269 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4116,6 +4116,15 @@
# Allow Instructor to do a Common Cartridge Export from Lessons
# DEFAULT: true
# lessonbuilder.cc-export=false

# Whether or not to force new HTML content as inline even if it doesn't have the attribute. See LSNBLDR-455, LSNBLDR-311
# DEFAULT: false
# lessonbuilder.cc.import.forceinline=true

# Whether or not to create new on a single lessons page new separate pages when importing content. Default create everything on new pages LSNBLDR-311
# DEFAULT: false
# lessonbuilder.cc.import.singlepage=true

## END LESSONBUILDER

# If you don't want to use ui.service as the Production name, use:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public InputSource resolveEntity(String publicId, String systemId) {
public void
processDependencies(DefaultHandler the_handler,
Element the_resource) throws ParseException {
for (Iterator iter=the_resource.getChildren(DEPENDENCY, the_handler.getNs().cc_ns()).iterator(); iter.hasNext();) {
for (Iterator iter=the_resource.getChildren(DEPENDENCY, the_handler.getNs().getNs()).iterator(); iter.hasNext();) {
String target=((Element)iter.next()).getAttributeValue(IDREF);
Element resource=findResource(the_handler.getNs(),target,the_resource.getParentElement());
the_handler.startDependency(the_resource.getAttributeValue(ID),target);
Expand All @@ -110,18 +110,18 @@ public InputSource resolveEntity(String publicId, String systemId) {
public void
processFiles(DefaultHandler the_handler,
Element the_resource) {
for (Iterator iter=the_resource.getChildren(FILE, the_handler.getNs().cc_ns()).iterator(); iter.hasNext();) {
the_handler.addFile(((Element)iter.next()).getAttributeValue(HREF));
for (Iterator iter=the_resource.getChildren(FILE, the_handler.getNs().getNs()).iterator(); iter.hasNext();) {
the_handler.addFile((Element)iter.next());
}
}

public void
processResourceMetadata(DefaultHandler the_handler,
Element the_resource) throws ParseException {
Element md = the_resource.getChild(METADATA, the_handler.getNs().cc_ns());
Element md = the_resource.getChild(METADATA, the_handler.getNs().getNs());
if (md != null) {
the_handler.checkCurriculum(md);
md=the_resource.getChild(METADATA, the_handler.getNs().cc_ns()).getChild(MD_ROOT, the_handler.getNs().lom_ns());
md=the_resource.getChild(METADATA, the_handler.getNs().getNs()).getChild(MD_ROOT, the_handler.getNs().lom_ns());
if (md!=null) {
the_handler.setResourceMetadataXml(md);
}
Expand Down Expand Up @@ -173,7 +173,7 @@ public InputSource resolveEntity(String publicId, String systemId) {
try {
String query=RESOURCE_QUERY.replaceFirst("xxx", the_identifier);
XPath path=XPath.newInstance(query);
path.addNamespace(ns.cc_ns());
path.addNamespace(ns.getNs());
result= (Element)path.selectSingleNode(the_resources);
} catch (JDOMException e) {
throw new ParseException(e.getMessage(),e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public void setResourceMetadataXml(Element the_md) {}

public void startManifestMetadata(String schema, String schema_version) {}

public void addFile(Element elem) {}

public void addFile(String the_file) {}

public void endLearningApplicationResource() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

public class Ns {
private int version = 0;
//Default namespace
private Namespace ns = CP_NS[0];
private Namespace lom = LOMIMSCC_NS[0];

private static final Namespace LOM_NS[] = {Namespace.getNamespace("lom", "http://ltsc.ieee.org/xsd/LOM"),
Namespace.getNamespace("lom", "http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource"),
Expand All @@ -22,11 +25,20 @@ public class Ns {
Namespace.getNamespace("lom", "http://ltsc.ieee.org/xsd/imsccv1p2/LOM/manifest"),
Namespace.getNamespace("lom", "http://ltsc.ieee.org/xsd/imsccv1p3/LOM/manifest")};

private static final Namespace LOMIMSCP_NS[] = {Namespace.getNamespace("lom", "http://www.imsglobal.org/xsd/imsmd_v1p2"),
Namespace.getNamespace("lom", "http://www.imsglobal.org/xsd/imsmd_v1p2"),
Namespace.getNamespace("lom", "http://www.imsglobal.org/xsd/imsmd_v1p2")};


private static final Namespace CC_NS[] = {Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imscc/imscp_v1p1"),
Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1"),
Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imsccv1p2/imscp_v1p1"),
Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imsccv1p3/imscp_v1p1")};

private static final Namespace CP_NS[] = {Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imscp_v1p1"),
Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imscp_v1p1"),
Namespace.getNamespace("ims", "http://www.imsglobal.org/xsd/imscp_v1p1")};

private static final Namespace TOPIC_NS[] = {Namespace.NO_NAMESPACE,
Namespace.getNamespace("dt", "http://www.imsglobal.org/xsd/imsccv1p1/imsdt_v1p1"),
Namespace.getNamespace("dt", "http://www.imsglobal.org/xsd/imsccv1p2/imsdt_v1p2"),
Expand Down Expand Up @@ -82,6 +94,24 @@ public int getVersions() {
return 4;
}

public void setNs(Namespace ns) {
this.ns = ns;
}

public Namespace getNs() {
return ns;
}

public void setLom(Namespace ns) {
this.lom = ns;
}

public Namespace getLom() {
return lom;
}



public Namespace lom_ns() {
return LOM_NS[version];
}
Expand All @@ -90,10 +120,19 @@ public Namespace lomimscc_ns() {
return LOMIMSCC_NS[version];
}

public Namespace lomimscp_ns() {
return LOMIMSCP_NS[version];
}

public Namespace cc_ns() {
return CC_NS[version];
}

public Namespace cp_ns() {
return CP_NS[version];
}


public Namespace topic_ns() {
return TOPIC_NS[version];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
* The parser will read the manifest file, as well as any declared xml resources (question banks, assessments, discussions,
* and weblinks). DefaultHandler will always return xml in the form of JDOM elements, as well as (in some cases), java
* objects (strings mostly). The parser will also return the details for authorization services, metadata and indicate if
* a resource is protected or not.
* a resource is protected or not
*
* @author Phil Nicholls
* @version 1.0
Expand All @@ -77,11 +77,12 @@

public class Parser extends AbstractParser {
private static final Logger log = LoggerFactory.getLogger(Parser.class);
CartridgeLoader utils;
CartridgeLoader utils;

private static final String IMS_MANIFEST="imsmanifest.xml";

private static final String AUTH_QUERY="/ims:manifest/auth:authorizations";
private static final String ORG_QUERY="/ims:manifest/ims:organizations/ims:organization";
private static final String ITEM_QUERY="/ims:manifest/ims:organizations/ims:organization/ims:item";

private static final String AUTH_IMPORT="import";
Expand Down Expand Up @@ -133,38 +134,48 @@ public class Parser extends AbstractParser {
// figure out which version we have, and set up ns to know about it
int v = 0;
for (; v < ns.getVersions(); v++) {
ns.setVersion(v);
// see if the namespace from the main manifest entry matches the candidate
if (the_manifest.getNamespace().equals(ns.cc_ns()))
break;
ns.setVersion(v);
// see if the namespace from the main manifest entry matches the candidate
if (the_manifest.getNamespace().equals(ns.cc_ns())) {
ns.setNs(ns.cc_ns());
ns.setLom(ns.lomimscc_ns());
break;
}
else if (the_manifest.getNamespace().equals(ns.cp_ns())) {
ns.setNs(ns.cp_ns());
ns.setLom(ns.lomimscp_ns());
break;
}
}
if (v >= ns.getVersions()) {
the_handler.getSimplePageBean().setErrMessage(
the_handler.getSimplePageBean().getMessageLocator().getMessage("simplepage.wrong-cc-version"));
return;
}

//log.info("Found version " + ns.cc_ns());
log.debug("Found version " + ns.getNs());

the_handler.startManifest();
the_handler.setManifestXml(the_manifest);
if (processAuthorization(the_manifest, the_handler))
return; // don't process CCs with authorization
processManifestMetadata(the_manifest, the_handler);
XPath path=null;
Element org=null;
try {
XPath path=XPath.newInstance(ITEM_QUERY);
path.addNamespace(ns.cc_ns());
Element item = (Element)path.selectSingleNode(the_manifest);
if (item!=null) {
for (Iterator iter=item.getChildren(CC_ITEM, ns.cc_ns()).iterator();iter.hasNext();) {
path=XPath.newInstance(ORG_QUERY);
path.addNamespace(ns.getNs());
org = (Element)path.selectSingleNode(the_manifest);
if (org!=null) {
for (Iterator iter=org.getChildren(CC_ITEM, ns.getNs()).iterator();iter.hasNext();) {
Element thisitem = (Element)iter.next();
processItem((Element)thisitem, the_manifest.getChild(CC_RESOURCES, ns.cc_ns()), the_handler);
processItem((Element)thisitem, the_manifest.getChild(CC_RESOURCES, ns.getNs()), the_handler);
}
}
//now we need to check for the question bank and omitted dependencies
if (the_manifest.getChild(CC_RESOURCES, ns.cc_ns()) != null &&
the_manifest.getChild(CC_RESOURCES, ns.cc_ns()).getChildren(CC_RESOURCE, ns.cc_ns()) != null)
for (Iterator iter=the_manifest.getChild(CC_RESOURCES, ns.cc_ns()).getChildren(CC_RESOURCE, ns.cc_ns()).iterator(); iter.hasNext(); ) {
if (the_manifest.getChild(CC_RESOURCES, ns.getNs()) != null &&
the_manifest.getChild(CC_RESOURCES, ns.getNs()).getChildren(CC_RESOURCE, ns.getNs()) != null)
for (Iterator iter=the_manifest.getChild(CC_RESOURCES, ns.getNs()).getChildren(CC_RESOURCE, ns.getNs()).iterator(); iter.hasNext(); ) {
// this is called for question banks and other things that aren't really items, but that's OK
Element resource=(Element)iter.next();
// create the resource if it wasn't already on a page
Expand All @@ -173,20 +184,20 @@ public class Parser extends AbstractParser {
}
the_handler.endManifest();
} catch (JDOMException e) {
System.err.println(e.getMessage());
log.warn(e.getMessage());
throw new ParseException(e.getMessage(),e);
}
}

private void
processManifestMetadata(Element manifest,
DefaultHandler the_handler) {
Element metadata=manifest.getChild(MD, ns.cc_ns());
Element metadata=manifest.getChild(MD, ns.getNs());
if (metadata!=null) {
the_handler.startManifestMetadata(metadata.getChildText(MD_SCHEMA, ns.cc_ns()),
metadata.getChildText(MD_SCHEMA_VERSION, ns.cc_ns()));
the_handler.startManifestMetadata(metadata.getChildText(MD_SCHEMA, ns.getNs()),
metadata.getChildText(MD_SCHEMA_VERSION, ns.getNs()));
the_handler.checkCurriculum(metadata);
Element lom=metadata.getChild(MD_ROOT, ns.lomimscc_ns());
Element lom=metadata.getChild(MD_ROOT, ns.getLom());
if (lom!=null) {
the_handler.setManifestMetadataXml(lom);
the_handler.endManifestMetadata();
Expand All @@ -201,7 +212,7 @@ public class Parser extends AbstractParser {
DefaultHandler the_handler) throws ParseException {
try {
XPath path=XPath.newInstance(AUTH_QUERY);
path.addNamespace(ns.cc_ns());
path.addNamespace(ns.getNs());
path.addNamespace(ns.auth_ns());
Element result=(Element)path.selectSingleNode(the_manifest);
if (result!=null) {
Expand Down Expand Up @@ -232,37 +243,46 @@ public class Parser extends AbstractParser {

private void
processItem(Element the_item,
Element the_resources,
DefaultHandler the_handler) throws ParseException {
try {
if (the_item.getAttributeValue(CC_ITEM_IDREF)!=null) {
Element resource=findResource(the_handler.getNs(),the_item.getAttributeValue(CC_ITEM_IDREF), the_resources);
if (resource == null) {
the_handler.getSimplePageBean().setErrKey("simplepage.cc-noresource", the_item.getAttributeValue(CC_ITEM_IDREF));
return;
}
// log.info("process item " + the_item + " resources " + the_resources + " resource " + resource);
Element the_resources,
DefaultHandler the_handler) throws ParseException {
try {
if (the_item.getAttributeValue(CC_ITEM_IDREF)!=null) {
Element resource=findResource(ns,the_item.getAttributeValue(CC_ITEM_IDREF), the_resources);
if (resource == null) {
the_handler.getSimplePageBean().setErrKey("simplepage.cc-noresource", the_item.getAttributeValue(CC_ITEM_IDREF));
return;
}
log.debug("process item " + the_item + " resources " + the_resources + " resource " + resource);

the_handler.startCCItem(the_item.getAttributeValue(CC_ITEM_ID),
the_item.getChildText(CC_ITEM_TITLE, ns.cc_ns()));
the_handler.setCCItemXml(the_item, resource, this, utils, false);
processResource(resource,
the_handler.startCCItem(the_item.getAttributeValue(CC_ITEM_ID),
the_item.getChildText(CC_ITEM_TITLE, ns.getNs()));
the_handler.setCCItemXml(the_item, resource, this, utils, false);
processResource(resource,
the_handler);
the_handler.endCCItem();
} else {
the_handler.startCCFolder(the_item);
for (Iterator iter=the_item.getChildren(CC_ITEM, ns.cc_ns()).iterator();iter.hasNext();) {
processItem((Element)iter.next(), the_resources, the_handler);
}
the_handler.endCCFolder();
}
} catch (Exception e) {
e.printStackTrace();
if (the_item == null)
log.info("processitem the item null");
else
log.info("processitem failed " + the_item.getAttributeValue(CC_ITEM_IDREF));
}
the_handler.endCCItem();
} else {

//CP formats don't follow the hierarchy standard at
//http://www.imsglobal.org/cc/ccv1p0/imscc_profilev1p0.html#0_pgfId-1753534
//So we need to skip the ones where title isn't defined (which would indicate that it is a valid folder and not just containing sub-items)
String title = the_item.getChildText(CC_ITEM_TITLE, ns.getNs());
if (title != null) {
the_handler.startCCFolder(the_item);
}
for (Iterator iter=the_item.getChildren(CC_ITEM, ns.getNs()).iterator();iter.hasNext();) {
processItem((Element)iter.next(), the_resources, the_handler);
}
if (title != null) {
the_handler.endCCFolder();
}
}
} catch (Exception e) {
e.printStackTrace();
if (the_item == null)
log.info("processitem the item null");
else
log.info("processitem failed " + the_item.getAttributeValue(CC_ITEM_IDREF));
}
}

public static Parser
Expand Down
Loading

0 comments on commit 03caa06

Please sign in to comment.