| 1 | from collective.imstransport.utilities.imsinterchange import IMSReader |
|---|
| 2 | from collective.imstransport.utilities.packagingio import ZipfileReader |
|---|
| 3 | from collective.imstransport.utilities.bb.bbreader import BBReader |
|---|
| 4 | from zope.component import getUtility |
|---|
| 5 | from collective.imstransport.utilities.interfaces import IIMSObjectCreator |
|---|
| 6 | from xml.parsers.expat import ExpatError |
|---|
| 7 | from collective.imstransport.IMS_exceptions import ManifestError |
|---|
| 8 | import re |
|---|
| 9 | |
|---|
| 10 | class IMSBBReader(IMSReader): |
|---|
| 11 | """ Create objects from IMS manifest. """ |
|---|
| 12 | |
|---|
| 13 | def readPackage(self, file, context): |
|---|
| 14 | """ Read the manifest """ |
|---|
| 15 | source = ZipfileReader(file) |
|---|
| 16 | objDict = {} |
|---|
| 17 | if not source: |
|---|
| 18 | return False, 'Internal error. No source object specified' |
|---|
| 19 | bbreader = BBReader() |
|---|
| 20 | manifest = source.readManifest() |
|---|
| 21 | if not manifest: |
|---|
| 22 | raise ManifestError, 'Could not locate manifest file "imsmanifest.xml" in the zip archive.' |
|---|
| 23 | try: |
|---|
| 24 | doc = bbreader.parseManifest(manifest) |
|---|
| 25 | except ExpatError, e: |
|---|
| 26 | raise ManifestError, str(e) |
|---|
| 27 | tocpages = [] |
|---|
| 28 | orgs = bbreader.readOrganizations(doc) |
|---|
| 29 | resources = bbreader.readResources(doc) |
|---|
| 30 | for x in resources: |
|---|
| 31 | resid, restype, bbfile, bbtitle, bbase = bbreader.readResourceAttributes(x) |
|---|
| 32 | if restype == 'resource/x-bb-document': |
|---|
| 33 | metadata = {} |
|---|
| 34 | # read the data file |
|---|
| 35 | if bbfile: |
|---|
| 36 | dataxml = source.readFile(bbfile) |
|---|
| 37 | resnode = bbreader.parseDataFile(dataxml) |
|---|
| 38 | metadata = bbreader.readMetadata(resnode) |
|---|
| 39 | files = bbreader.readFiles(x) |
|---|
| 40 | # If the resource is a file |
|---|
| 41 | if files: |
|---|
| 42 | hash = resid |
|---|
| 43 | objDict[hash] = metadata |
|---|
| 44 | excludeFromNav = True |
|---|
| 45 | file = '%s/%s' %(bbase, files[0]) |
|---|
| 46 | type = self.determineType(objDict[hash], files[0]) |
|---|
| 47 | id = self.createIdFromFile(files[0]) |
|---|
| 48 | path = '%s' %bbase |
|---|
| 49 | if orgs.has_key(resid): |
|---|
| 50 | title = orgs[resid] |
|---|
| 51 | else: |
|---|
| 52 | title = id |
|---|
| 53 | self.applyCoreMetadata(objDict, hash, id, path, excludeFromNav, type, title, file=file) |
|---|
| 54 | # If the resource is a document |
|---|
| 55 | else: |
|---|
| 56 | hash = resid |
|---|
| 57 | objDict[hash] = metadata |
|---|
| 58 | excludeFromNav = True |
|---|
| 59 | type = 'Document' |
|---|
| 60 | id = resid |
|---|
| 61 | path = '' |
|---|
| 62 | if orgs.has_key(resid): |
|---|
| 63 | title = orgs[resid] |
|---|
| 64 | else: |
|---|
| 65 | title = id |
|---|
| 66 | self.applyCoreMetadata(objDict, hash, id, path, excludeFromNav, type, title) |
|---|
| 67 | # The resource is a table of contents page. |
|---|
| 68 | elif restype == 'course/x-bb-coursetoc': |
|---|
| 69 | hash = resid |
|---|
| 70 | objDict[hash] = {} |
|---|
| 71 | excludeFromNav = False |
|---|
| 72 | tocpages.append(resid) |
|---|
| 73 | type = 'Document' |
|---|
| 74 | path = '' |
|---|
| 75 | id = resid |
|---|
| 76 | if orgs.has_key(resid): |
|---|
| 77 | title = re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', orgs[resid].split('.')[1]) |
|---|
| 78 | else: |
|---|
| 79 | title = id |
|---|
| 80 | self.applyCoreMetadata(objDict, hash, id, path, excludeFromNav, type, title) |
|---|
| 81 | |
|---|
| 82 | # Build table of contents pages |
|---|
| 83 | for z in tocpages: |
|---|
| 84 | text = '<table>' |
|---|
| 85 | tocitems = bbreader.readTocItem(doc, z) |
|---|
| 86 | for titem in tocitems: |
|---|
| 87 | met = objDict[titem] |
|---|
| 88 | path = met['path'] |
|---|
| 89 | if path: |
|---|
| 90 | linkpath = '%s/%s' %(path, objDict[titem]['id']) |
|---|
| 91 | else: |
|---|
| 92 | linkpath = objDict[titem]['id'] |
|---|
| 93 | text += "<tr><td><a href='%s/view'>%s</a></td></tr>" %(linkpath, objDict[titem]['title']) |
|---|
| 94 | text += '</table>' |
|---|
| 95 | objDict[z]['text'] = text |
|---|
| 96 | |
|---|
| 97 | objcreator = getUtility(IIMSObjectCreator) |
|---|
| 98 | objcreator.createObjects(objDict, context, source) |
|---|
| 99 | |
|---|
| 100 | def applyCoreMetadata(self, objDict, hash, id, path, excludeFromNav, type, title, file=None, text=None): |
|---|
| 101 | """ Helper function for applying metadata """ |
|---|
| 102 | objDict[hash]['id'] = id |
|---|
| 103 | objDict[hash]['path'] = path |
|---|
| 104 | objDict[hash]['excludeFromNav'] = excludeFromNav |
|---|
| 105 | if not (objDict[hash].has_key('type') and objDict[hash]['type']): |
|---|
| 106 | objDict[hash]['type'] = type |
|---|
| 107 | if not (objDict[hash].has_key('title') and objDict[hash]['title']): |
|---|
| 108 | objDict[hash]['title'] = title |
|---|
| 109 | if file: |
|---|
| 110 | objDict[hash]['file'] = file |
|---|
| 111 | if text: |
|---|
| 112 | objDict[hash]['text'] = text |
|---|
| 113 | |
|---|