Changeset 306


Ignore:
Timestamp:
06/26/09 15:57:22 (5 years ago)
Author:
jon
Message:

Changes to imscp writer and read to bring in line with common cartridge refactor

Location:
collective.imstransport/trunk/collective/imstransport/utilities/imscp
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • collective.imstransport/trunk/collective/imstransport/utilities/imscp/cpreader.py

    r197 r306  
    11from xml.dom import minidom 
    22from collective.imstransport.IMS_exceptions import ManifestError 
     3from configcp import LOM_IMSCP_namespace 
    34 
    45class CPReader(object): 
    5  
    6     def __init__(self, context, source): 
    7         """ 
    8         """ 
    9         self.context = context 
    10         self.document = None 
    11         self.orgdata = {} 
    12         self.resids = [] 
    13         self.objdict = {} 
    146 
    157    def parseManifest(self, manifest): 
    168        """ parse the manifest """ 
    17         self.document = minidom.parseString(manifest) 
    18  
    19     def readManifests(self): 
     9        return minidom.parseString(manifest) 
     10 
     11    def readPackageMetadata(self, manifest): 
     12        """ Read the package metadata """ 
     13        return self.readMetadata(manifest) 
     14 
     15    def readOrganizations(self, manifest): 
    2016        """ Read the organizations section of the manifest. """ 
    21         self.org = {} 
    22         organizations = self.document.getElementsByTagName('organizations') 
     17        orgs = {} 
     18        organizations = manifest.getElementsByTagName('organizations') 
    2319        if organizations: 
    24             self._readItems(self.context, organizations[0]) 
    25         else: 
    26             raise ManifestError, 'Manifest file has no "organizations" section.' 
    27      
    28     def readOrganizations(self): 
    29         """ Read the organizations section of the manifest. """ 
    30         self.org = {} 
    31         organizations = self.document.getElementsByTagName('manifest') 
    32         if organizations: 
    33             return self._readItems(self.context, organizations[0]) 
    34         else: 
    35             raise ManifestError, 'Manifest file has no "organizations" section.' 
    36  
    37     def _readItems(self, object, orgs): 
    38         """ Read items from the manifest. """ 
    39  
    40         organization_nodes = orgs.getElementsByTagName('organization') 
    41         if organization_nodes: 
    42             organization_node = organization_nodes[0] 
    43              
    44             item_nodes = organization_nodes[0].getElementsByTagName('item') 
    45             itemnum = 1 
    46             for item in item_nodes: 
    47                 idref = item.getAttribute('identifierref') 
    48                 title_nodes = item.getElementsByTagName('title') 
    49                 if title_nodes: 
    50                     self.orgdata[idref] = self.getTextValue(title_nodes[0]) 
     20            organization_nodes = organizations[0].getElementsByTagName('organization') 
     21            if organization_nodes: 
     22                organization_node = organization_nodes[0] 
     23                item_nodes = organization_nodes[0].getElementsByTagName('item') 
     24                itemnum = 1 
     25                for item in item_nodes: 
     26                    idref = item.getAttribute('identifierref') 
     27                    titlenodes = item.getElementsByTagName('title') 
     28                    if titlenodes: 
     29                        orgs[idref] = (itemnum, self.getTextValue(titlenodes[0])) 
     30                    else: 
     31                        orgs[idref] = (itemnum, None) 
    5132                    itemnum += 1 
    52                  
    53         return self.orgdata 
    54  
    55     def readResources(self): 
     33        return orgs 
     34 
     35    def readResources(self, manifest): 
    5636        """ Read all resources. """ 
    57         resources = self.document.getElementsByTagName('resources') 
     37        reslist = [] 
     38        resources = manifest.getElementsByTagName('resources') 
    5839        if resources: 
    59             for res in resources[0].getElementsByTagName('resource'): 
    60                 id = res.getAttribute('identifier') 
    61                 self.resids.append(id) 
    62  
    63         return self.resids 
    64  
    65     def getResourceIds(self): 
    66         """ Get a list of resource identifiers """ 
    67         return self.resids 
     40            reslist =  resources[0].getElementsByTagName('resource') 
     41        return reslist 
    6842 
    6943    def getTextValue(self, node): 
     
    7448        return None 
    7549 
    76  
    77     def getVcardValues(self, node, resid): 
     50    def readResourceAttributes(self, resource): 
     51        """ Return attributes on resource node. """ 
     52        return (resource.getAttribute('identifier'), 
     53                resource.getAttribute('type'), 
     54                resource.getAttribute('href')) 
     55 
     56    def readMetadata(self, metadata): 
     57        md = {} 
     58        self.readGeneral(metadata, md) 
     59        self.readLifecycle(metadata, md) 
     60        self.readMetaMetadata(metadata, md) 
     61        self.readTechnical(metadata, md) 
     62        self.readRights(metadata, md) 
     63        return md 
     64 
     65    def readFiles(self, resource): 
     66        files = [] 
     67        flns = resource.getElementsByTagName('file') 
     68        if flns: 
     69            for fln in flns: 
     70                file = fln.getAttribute('href') 
     71                files.append(file) 
     72        return files 
     73 
     74    def readGeneral(self, metadata, md): 
     75        """ Read general node """ 
     76        gen_node = None 
     77        gen_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'general') 
     78        if gen_nodes: 
     79            gen_node = gen_nodes[0] 
     80            title_nodes = gen_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'title')         
     81            if title_nodes: 
     82                langstring_nodes = title_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace,'langstring') 
     83                if langstring_nodes: 
     84                    title = self.getTextValue(langstring_nodes[0]) 
     85                    if title: 
     86                        md['title'] = title 
     87            if not md.has_key('title'): 
     88                raise ManifestError, 'Required tag "title" missing in lom/general metadata section for resource.' 
     89            language_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'language') 
     90            if language_nodes: 
     91                lang = self.getTextValue(language_nodes[0]) 
     92                if lang: 
     93                    md['language'] = lang 
     94            desc_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'description') 
     95            if desc_nodes: 
     96                langstring_nodes = desc_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace,'langstring') 
     97                if langstring_nodes: 
     98                    description = self.getTextValue(langstring_nodes[0]) 
     99                    if description: 
     100                        md['description'] = description 
     101            kw_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'keyword') 
     102            if kw_nodes: 
     103                kw_list = [] 
     104                for kw_node in kw_nodes: 
     105                    kw_lang_nodes = kw_node.getElementsByTagNameNS(LOM_IMSCP_namespace,'langstring') 
     106                    if kw_lang_nodes: 
     107                        for lang_node in kw_lang_nodes: 
     108                            kw = self.getTextValue(lang_node) 
     109                            if kw: 
     110                                kw_list.append(kw) 
     111                if kw_list: 
     112                    md['subject'] = kw_list 
     113     
     114    def readLifecycle(self, metadata, md): 
     115        """ Read Lifecycle node """ 
     116        lc_node = None 
     117        lc_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'lifecycle') 
     118        if lc_nodes: 
     119            lc_node = lc_nodes[0] 
     120        if lc_node: 
     121            # Lifecycle Node 
     122            contribute_nodes = lc_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'contribute') 
     123            # For each contribute node there is a role node, a centity node, and possibly a date node 
     124            for contribute_node in contribute_nodes: 
     125                source = '' 
     126                value = '' 
     127                vlist = [] 
     128                datetime = '' 
     129                role_nodes = contribute_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'role') 
     130                if role_nodes: 
     131                    source_nodes = role_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace, 'source') 
     132                    if source_nodes: 
     133                        langstring_nodes = source_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace, 'langstring') 
     134                        if langstring_nodes: 
     135                            source = self.getTextValue(langstring_nodes[0]) 
     136                    value_nodes = role_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace, 'value') 
     137                    if value_nodes: 
     138                        langstring_nodes = value_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace, 'langstring') 
     139                        if langstring_nodes: 
     140                            value = self.getTextValue(langstring_nodes[0]) 
     141                entity_nodes = contribute_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'centity') 
     142                for entity_node in entity_nodes: 
     143                    vcard = entity_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'vcard') 
     144                    if vcard: 
     145                        name, email = self.getVcardValues(vcard[0]) 
     146                        if value: 
     147                            vlist.append((name, email)) 
     148                date_nodes = contribute_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'date') 
     149                if date_nodes: 
     150                    datetime_nodes = date_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace, 'datetime') 
     151                    if datetime_nodes: 
     152                        datetime = self.getTextValue(datetime_nodes[0]) 
     153                # Creator 
     154                if 'author' == value.lower() and vlist: 
     155                    md['creators'] = [x[0] for x in vlist] 
     156                    if datetime: 
     157                        md['creation_date'] = datetime 
     158                # Contributors 
     159                if 'unknown' == value.lower() and vlist: 
     160                    md['contributors'] = [x[0] for x in vlist] 
     161 
     162    def readMetaMetadata(self, metadata, md): 
     163        """ Read MetaMetadata node """ 
     164 
     165    def readTechnical(self, metadata, md): 
     166        """ Read the Technical node """ 
     167        tec_node = None 
     168        tec_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'technical') 
     169        if tec_nodes: 
     170            tec_node = tec_nodes[0] 
     171            format_nodes = tec_node.getElementsByTagNameNS(LOM_IMSCP_namespace, 'format') 
     172            if format_nodes: 
     173                format = self.getTextValue(format_nodes[0]) 
     174                if format: 
     175                    md['Format'] = format 
     176 
     177    def readRights(self, metadata, md): 
     178        """ Read Rights node """ 
     179        rights_node = None 
     180        rights_nodes = metadata.getElementsByTagNameNS(LOM_IMSCP_namespace, 'rights') 
     181        if rights_nodes: 
     182            rights_node = rights_nodes[0] 
     183            description_nodes = rights_node.getElementsByTagNameNS(LOM_IMSCP_namespace,'description') 
     184            if description_nodes: 
     185                langstring_nodes = description_nodes[0].getElementsByTagNameNS(LOM_IMSCP_namespace,'langstring') 
     186                if langstring_nodes: 
     187                    description = self.getTextValue(langstring_nodes[0]) 
     188                    if description: 
     189                        md['rights'] = description 
     190 
     191    def getVcardValues(self, node): 
    78192        """ 
    79         Looks for the full name and email values in a VCARD 
    80         value. 
    81  
    82         Added some whitespace stripping, and case 
    83         insensitive tag searching, so that we could parse the 
    84         default IMS example package. 
    85      
     193        Looks for the full name and email values in a VCARD value. 
    86194        """ 
    87195        text = self.getTextValue(node) 
    88196        textlines = text.strip().split('\n') 
    89                  
    90         value = self._getVcardValue('BEGIN', [textlines[0]]) 
     197        value = self.getVcardValue('BEGIN', [textlines[0]]) 
    91198        if 'VCARD' != value.strip().upper(): 
    92             raise ManifestError, 'Missing VCARD BEGIN tag for resource "%s"' %resid 
    93  
    94         value = self._getVcardValue('END', [textlines[-1]]) 
     199            raise ManifestError, 'Missing VCARD BEGIN tag' 
     200        value = self.getVcardValue('END', [textlines[-1]]) 
    95201        if 'VCARD' != value.strip().upper(): 
    96             raise ManifestError, 'Missing VCARD END tag for resource "%s"' %resid 
    97              
    98         name = self._getVcardValue('FN', textlines) 
    99         email = self._getVcardValue('EMAIL;INTERNET', textlines) 
    100  
     202            raise ManifestError, 'Missing VCARD END tag' 
     203        name = self.getVcardValue('FN', textlines) 
     204        email = self.getVcardValue('EMAIL;INTERNET', textlines) 
    101205        return name, email 
    102  
    103206         
    104     def _getVcardValue(self, field, text): 
     207    def getVcardValue(self, field, text): 
    105208        """ Try to get a value for a VCARD field. """ 
    106209        for textline in text: 
    107             # If the line is not folded 
    108             #if textline[0] != ' ': 
    109                 # Look for the Colon delimiter 
    110210            textline = textline.strip() 
    111211            if textline.find(':'): 
  • collective.imstransport/trunk/collective/imstransport/utilities/imscp/cpwriter.py

    r188 r306  
    33import md5 
    44import os 
    5  
    6  
    7 LOM_version = 'LOMv1.0' 
    8 LOM_namespace = 'http://ltsc.ieee.org/xsd/LOM' 
     5from configcp import LOM_IMSCP_namespace, namespaces, schema_locations, LOM_version, IMS_schema, IMS_version 
    96 
    107class CPWriter(object): 
    118 
    12     def __init__(self, context): 
    13         self.context = context 
     9    def __init__(self): 
    1410        self.document = minidom.Document() 
    15         self.destination = None 
    16         self.manifest_node = None 
    17         self.custom_namespaces = None 
    18         self.extensionMetadata = None 
    19         self.itemDict = {} 
    20  
    21     def setExtensionNamespaces(self, extension_ns): 
    22         """ Set any extension namespaces """ 
    23         self.namespaces += extension_ns 
    24  
    25     def setDestination(self, destination): 
    26         """ Set the output object for the writer. """ 
    27         self.destination = destination 
    28  
    29     def setExtensionMetadataMethod(self, extensionMetadata): 
    30         """ Set the extension metadata method """     
    31         self.extensionMetadata = extensionMetadata 
    32  
     11 
     12    def createManifest(self, id, ver): 
     13        """ Create a new empty manifest. """ 
     14        doc = minidom.Document() 
     15        manifest = self._createNode(doc, '', 'manifest',  
     16                         attrs=[('identifier', id), 
     17                                ('xmlns:version', ver),]) 
     18        self.addNamespaces(manifest, namespaces) 
     19        self.addSchemaLocations(manifest, schema_locations) 
     20        return doc 
     21 
     22    def writeTopLevelMetadata(self, doc, id, title, urlbase, lang, desc=None, keywords=None): 
     23        """ Write top level metadata into the manifest. """ 
     24        manifest = doc.getElementsByTagName('manifest') 
     25        if manifest: 
     26            md = self._createNode(manifest[0], '', 'metadata') 
     27            self._createNode(md, '', 'schema', IMS_schema) 
     28            self._createNode(md, '', 'schemaversion', IMS_version) 
     29            lom = self._createNode(md, LOM_IMSCP_namespace, 'lom') 
     30            self.writeGeneralNode(lom, id,  title, lang, desc, keywords) 
     31 
     32    def createOrganizations(self, doc, orgId): 
     33        """ Create an organizations section in the manifest """ 
     34        manifest = doc.getElementsByTagName('manifest') 
     35        if manifest: 
     36            orgs = self._createNode(manifest[0], '', 'organizations', attrs=[('default', orgId),]) 
     37            org = self._createNode(orgs, '', 'organization', attrs=[('identifier', orgId),]) 
     38            return org 
     39        return None 
     40 
     41    def createResources(self, doc): 
     42        manifest = doc.getElementsByTagName('manifest') 
     43        if manifest: 
     44            return self._createNode(manifest[0], '', 'resources') 
     45        return None 
     46                          
     47    def writeItem(self, orgs, itemId, refId, title): 
     48        """ Write an item in the organizations section """ 
     49        itn = self._createNode(orgs, '', 'item', attrs=[('identifier', itemId), 
     50                                                        ('identifierref', refId), 
     51                                                        ('isvisible', 'true')]) 
     52        tn = self._createNode(itn, '', 'title', title) 
     53        return tn 
     54 
     55    def writeResource(self, res, refid, type, path): 
     56        """ Write a resource object in the resources section """ 
     57        attrs = [('identifier', refid)] 
     58        attrs.append(('type', 'webcontent')) 
     59        attrs.append(('href', path)) 
     60        rn = self._createNode(res, '', 'resource', attrs=attrs) 
     61        return rn 
     62 
     63    def createResourceMetadata(self, res): 
     64        """ Create a resource metadat node """ 
     65        md = self._createNode(res, '', 'metadata') 
     66        return self._createNode(md, LOM_IMSCP_namespace, 'lom') 
    3367     
    34     def writeManifestNode(self, manifestId, manifestVer, namespaces, schema_locations): 
    35         """ Write the manifest node. """ 
    36         self.manifest_node = self._createNode(self.document, 
    37                                               '', 
    38                                               'manifest',  
    39                                               attrs=[('identifier', manifestId), 
    40                                                      ('xmlns:version', manifestVer),]) 
    41         self.addNamespaces(namespaces) 
    42         self.addSchemaLocations(schema_locations) 
    43  
    44  
    45     def writeLOMCPMetadata(self, id, title, urlbase, imsschema, imsversion, lang=None, description=None, keywords=None): 
    46         """ Write the lom imscc metadata node for the top level object """ 
    47  
    48         # Create the top level Metadata node 
    49         self.metadata_node = self._createNode(self.manifest_node, '', 'metadata') 
    50  
    51  
    52         self.schema_node = self._createNode(self.metadata_node, 
    53                                             '', 
    54                                             'schema',  
    55                                             imsschema) 
    56  
    57         self.schema_node = self._createNode(self.metadata_node, 
    58                                             '', 
    59                                             'schemaversion',  
    60                                             imsversion) 
    61  
    62  
    63     def writeManifest(): 
    64  
    65         # Create the Organizations node 
    66         defaultId = self._createPathId(self.context.virtual_url_path(), 'ORG') 
    67         organizations_node = self._createNode(self.manifest_node, 
    68                                               '', 
    69                                               'organizations',) 
    70  
    71  
    72         # Write out organizations information. 
    73         self.writeOrganizations(self.context, organizations_node, self) 
    74  
    75         resources_node = self._createNode(self.manifest_node, '', 'resources') 
    76  
    77         allObjects = self._getAllObjects() 
    78          
    79         for obj in allObjects: 
    80             # Handle the case where an object might be folderish, but 
    81             # also has a text attribute. 
    82             if not obj.isPrincipiaFolderish or hasattr(obj.aq_explicit,'getText'): 
    83                 path = self._getObjectPath(obj) 
    84                 self._writeResource(obj, resources_node, path, extensionMetadata=self.extensionMetadata) 
    85                 self._writeObjectData(obj, path) 
    86  
    87         self._writeObjectData(self.getManifest(), 'imsmanifest.xml') 
    88  
    89         if self.destination: 
    90             return self.destination.getOutput() 
    91         else: 
    92             return None, None 
    93  
    94     def writeOrganizationsNode(self, id): 
    95         """ Common Cartridge requires organization to specify rooted-hierarchy as structure """ 
    96         self.organizations_node = self._createNode(self.manifest_node, 
    97                                                    '', 
    98                                                    'organizations', 
    99                                                    attrs=[('default',id)]) 
    100  
    101  
    102         self.organization_node = self._createNode(self.organizations_node, 
    103                                                   '', 
    104                                                   'organization', 
    105                                                   attrs=[('identifier',id)]) 
    106          
    107  
    108     def writeItem(self, itemId, title, refId=None): 
    109         """ Write out a single item and its title. Folder nodes include containing objects """ 
    110  
    111         attrs = [('identifier', itemId),] 
    112         if refId: 
    113             attrs.append(('identifierref', refId)) 
    114  
    115         item_node = self._createNode(self.organization_node, 
    116                                        '', 
    117                                        'item', 
    118                                        attrs=attrs) 
    119  
    120         self._createNode(item_node, '', 'title', title) 
    121  
    122  
    123     def writeResources(self): 
    124         """ Resources node """ 
    125         self.resources_node = self._createNode(self.manifest_node, '', 'resources') 
    126  
    127  
    128     def getResourceMetadataWriter(self, writer): 
    129         """ ResourceMetadataWriter objects create the resource node along with all metadata therein """ 
    130         return ResourceMetadataWriter(writer)                   
    131  
    132  
    133     def getManifest(self): 
     68    def writeGeneralNode(self, lom, id, title, lang, desc=None, kw=None): 
     69        """ Write the general Node """ 
     70        if not lang: 
     71            lang = 'x-none' 
     72        gen = self._createNode(lom, '', 'general') 
     73        idn = self._createNode(gen, '', 'identifier', id) 
     74        tn = self._createNode(gen, '', 'title') 
     75        self._createNode(tn, '', 'langstring', title, [('xml:lang', lang)]) 
     76        self._createNode(gen, '', 'language', lang) 
     77        if desc: 
     78            dn = self._createNode(gen, '', 'description') 
     79            self._createNode(dn, '', 'langstring', desc, [('xml:lang', lang)]) 
     80        if kw: 
     81            kn = self._createNode(gen, '', 'keyword') 
     82            for k in kw: 
     83                self._createNode(kn, '', 'langstring', k, [('xml:lang', lang)]) 
     84 
     85    def writeLifeCycleNode(self, lom, creators, contrib, mod, lang): 
     86        """ Write the lifecycle Node """ 
     87        if not lang: 
     88            lang = 'x-none' 
     89        ln = self._createNode(lom, '', 'lifecycle') 
     90        if creators: 
     91            self._createContributeElement(ln, '', LOM_version, 'author', lang, creators, mod) 
     92        if contrib: 
     93            self._createContributeElement(ln, '', LOM_version, 'unknown', lang, contrib, mod) 
     94 
     95    def writeMetaMetadataNode(self, lom, id, urlbase, email, modtime, lang, contrib): 
     96        """ write the metaMetadata Node """ 
     97        if not lang: 
     98            lang = 'x-none' 
     99        mmd = self._createNode(lom, '', 'metametadata') 
     100        idn = self._createNode(mmd, '', 'catalogentry') 
     101        catentry = urlbase 
     102        if email: 
     103            catentry += ',%s' %email 
     104        self._createNode(idn, '', 'catalog', catentry) 
     105        entry = self._createNode(idn, '', 'entry') 
     106        self._createNode(entry, '', 'langstring', id, attrs=[('xml:lang',lang)]) 
     107        self._createNode(mmd, '', 'metadatascheme', LOM_version) 
     108        self._createNode(mmd, '', 'language', lang) 
     109 
     110    def writeTechnicalNode(self, lom, format, size, location): 
     111        """ Write the Technical Node """ 
     112        tech = self._createNode(lom, '', 'technical') 
     113        self._createNode(tech, '', 'format', format) 
     114        self._createNode(tech, '', 'size', size) 
     115        self._createNode(tech, '', 'location', location) 
     116 
     117    def writeRightsNode(self, lom, value, copyright, lang):  
     118        """ Write the Rights Node """ 
     119        if not lang: 
     120            lang = 'x-none' 
     121        rights = self._createNode(lom, '', 'rights') 
     122        cwn = self._createNode(rights, '', 'copyrightandotherrestrictions') 
     123        source_node = self._createNode(cwn, '', 'source')            
     124        self._createNode(source_node, '', 'langstring', LOM_version, attrs=[('xml:lang', lang)]) 
     125        value_node = self._createNode(cwn, '', 'value') 
     126        self._createNode(value_node, '', 'langstring', value, attrs=[('xml:lang', lang)]) 
     127        if copyright: 
     128            desc = self._createNode(rights, '', 'description') 
     129            self._createNode(desc, '', 'langstring', copyright, [('xml:lang', lang)]) 
     130 
     131 
     132    def _createContributeElement(self, node,  ns, source, value, lang, entities=[], date=None, email=None): 
     133        """ writes out a Contribute Element """ 
     134        cn = self._createNode(node, ns, 'contribute') 
     135        role = self._createNode(cn, '', 'role') 
     136        source_node = self._createNode(role, '', 'source') 
     137        self._createNode(source_node, '', 'langstring', source, attrs=[('xml:lang', lang)]) 
     138        value_node = self._createNode(role, '', 'value') 
     139        self._createNode(value_node, '', 'langstring', value, attrs=[('xml:lang', lang)]) 
     140        if entities: 
     141            if type(entities) not in [type([]), type(())]: 
     142                entities = [entities] 
     143            for e in entities: 
     144                centity_node = self._createNode(cn, '', 'centity') 
     145                self._createNode(centity_node, '', 'vcard', self._createVCard(e,email)) 
     146        if date: 
     147            dn = self._createNode(cn, '', 'date') 
     148            self._createNode(dn, '', 'datetime', date) 
     149 
     150    def _createVCard(self, name, email=None): 
     151        """ 
     152        Writes out a VCard entry for a contribute element 
     153        Note: Should replace this with the python vcard library. 
     154        """ 
     155        vCard = 'BEGIN:VCARD\n' 
     156        vCard += 'FN:'+name+'\n' 
     157        if email: 
     158            vCard += 'EMAIL;INTERNET:'+email+'\n' 
     159        vCard += 'END:VCARD' 
     160        return vCard 
     161 
     162    def writeResourceFile(self, res, path): 
     163        """ Write a file node """ 
     164        self._createNode(res, '', 'file', attrs=[('href', path)]) 
     165 
     166 
     167    def getManifest(self, manifest): 
    134168        """ Get the manifest expressed in XML. """ 
    135         return self.document.toxml(encoding='utf-8') 
    136  
     169        return manifest.toxml(encoding='utf-8') 
    137170 
    138171    def _createNode(self, parent, nspace, ename, value=None, attrs=None): 
    139172        """ Create a node in the document. """ 
    140173        newnode = self.document.createElementNS(nspace, ename) 
     174        if nspace: 
     175            newnode.setAttribute('xmlns', nspace) 
    141176        parent.appendChild(newnode) 
    142177        if value and value != '': 
     
    144179                newnode.appendChild(self.document.createTextNode(value.decode('utf-8'))) 
    145180            else: 
    146                 newnode.appendChild(self.document.createTextNode(value))                 
     181                newnode.appendChild(self.document.createTextNode(value)) 
    147182        if attrs: 
    148183            for x in attrs: 
     
    150185        return newnode 
    151186 
    152  
    153     def addNamespaces(self, namespaces): 
    154         """ Add a list of namespace to the manifest. """ 
     187    def addNamespaces(self, manifest, namespaces): 
     188        """ Add a namespace to the manifest. """ 
    155189        for namespace in namespaces: 
    156             self.manifest_node.setAttribute(namespace[0], namespace[1]) 
    157  
    158     def addSchemaLocations(self, schema_locations): 
    159         self.manifest_node.setAttribute('xsi:schemaLocation', join(schema_locations, ' ')) 
    160  
     190            manifest.setAttribute(namespace[0], namespace[1]) 
     191 
     192    def addSchemaLocations(self, manifest, schema_locations): 
     193        manifest.setAttribute('xsi:schemaLocation', join(schema_locations, ' ')) 
    161194 
    162195    def getTextValue(self, node): 
     
    165198            if x.nodeType == x.TEXT_NODE: 
    166199                return x.nodeValue.strip() 
    167         return None         
     200        return None 
     201 
     202    def getLinkXml(self, title, link): 
     203        """ Return text for a file that stores the link in an xml file """ 
     204        doc = minidom.Document() 
     205        link_node = self._createNode(doc, '', 'a', title, attrs=[('href',link),]) 
     206        return doc.toxml() 
     207 
  • collective.imstransport/trunk/collective/imstransport/utilities/imscp/imscpreader.py

    r197 r306  
    1 from zope.interface import implements 
    2 from collective.imstransport.utilities.interfaces import IIMSObjectCreator 
    3 from zope.component import getUtility 
    4 from collective.imstransport.utilities.imsinterchange import IMSInterchangeReader 
     1from collective.imstransport.utilities.imsinterchange import IMSReader 
    52from collective.imstransport.utilities.packagingio import ZipfileReader 
    63from collective.imstransport.utilities.imscp.cpreader import CPReader 
    7 from collective.imstransport.utilities.imscp.cpresourcereader import CPResourceReader 
    8 import re 
    9 from collective.imstransport import IMSTransportMessageFactory as _ 
    10 from xml.dom import minidom 
     4from zope.component import getUtility 
     5from collective.imstransport.utilities.interfaces import IIMSObjectCreator 
    116 
    12 LOM_namespace = 'http://ltsc.ieee.org/xsd/LOM' 
    13  
    14 class IMSCPReader(IMSInterchangeReader): 
     7class IMSCPReader(IMSReader): 
    158    """ Create objects from IMS manifest. """ 
    16  
    17     name = _(u'IMS Content Package') 
    18  
    19     XML = 'http://www.w3.org/XML/1998/namespace' 
    20     IMSCP = 'http://www.imsglobal.org/xsd/imscc/imscp_v1p1' 
    21     LOM = 'http://ltsc.ieee.org/xsd/LOM' 
    229 
    2310    def readPackage(self, file, context): 
    2411        """ Read the manifest """ 
    2512 
    26         source = ZipfileReader(input) 
     13        source = ZipfileReader(file) 
    2714        objDict = {} 
    2815 
     
    3017             return False, 'Internal error. No source object specified' 
    3118 
    32         cpreader = CPReader(context, source) 
    33               
     19        cpreader = CPReader() 
    3420        manifest = source.readManifest() 
    3521        if not manifest: 
    36             return False, \ 
    37                    'Manifest', \ 
    38                    'Could not locate manifest file "imsmanifest.xml" in the zip archive.' 
     22            raise ManifestError, 'Could not locate manifest file "imsmanifest.xml" in the zip archive.' 
    3923 
    40         cpreader.parseManifest(manifest) 
    41         orgdata = cpreader.readOrganizations() 
    42         resourceids = cpreader.readResources() 
     24        try: 
     25            doc = cpreader.parseManifest(manifest) 
     26        except ExpatError, e: 
     27            raise ManifestError, str(e) 
     28        objDict['package'] = cpreader.readPackageMetadata(doc) 
     29        orgs = cpreader.readOrganizations(doc) 
     30        resources = cpreader.readResources(doc) 
    4331 
    44         for resourceid in resourceids: 
    45             cpresourcereader = CPResourceReader(cpreader, resourceid, 'http://www.imsglobal.org/xsd/imsmd_v1p2')             
    46             resdata = self.parseResourceMetadata(cpresourcereader, resourceid, context) 
    47             reshref = cpresourcereader.getHref() 
    48             files = cpresourcereader.readFiles() 
     32        for x in resources: 
     33            resid, restype, reshref = cpreader.readResourceAttributes(x) 
     34            metadata = cpreader.readMetadata(x) 
     35            files = cpreader.readFiles(x) 
    4936 
    50             hashref = '' 
    51             if files: 
    52                 for file in files: 
    53                     hashref = '%s%s' %(resourceid, file) 
    54                     id = self.createIdFromFile(file) 
    55                     path = self.createPathFromFile(file) 
     37            # If the type is a file 
     38            if restype == 'webcontent': 
     39                if not files and reshref: 
     40                    files = [reshref,] 
     41                for y in files: 
     42                    hash = resid + y 
     43                    # If there is only one file, or it matches the reshref 
     44                    # add the metadata to it if it exists 
     45                    if y == reshref or len(files) == 1: 
     46                        objDict[hash] = metadata 
     47                        # If it is listed in the org section 
     48                        if orgs.has_key(resid): 
     49                            objDict[hash]['position'] = orgs[resid][0] 
     50                            objDict[hash]['excludeFromNav'] = False 
     51                            # Use 'and' as opposed to 'or' to avoid KeyError 
     52                            if not (objDict[hash].has_key('title') and objDict[hash]['title']): 
     53                                objDict[hash]['title'] = orgs[resid][1] 
     54                        else: 
     55                            objDict[hash]['excludeFromNav'] = True 
     56                        objDict[hash]['file'] = y 
     57                        objDict[hash]['type'] = self.determineType(objDict[hash], y) 
     58                    # If it is just a lowly file 
     59                    else: 
     60                        objDict[hash] = {} 
     61                        objDict[hash]['excludeFromNav'] = True 
     62                        objDict[hash]['file'] = y 
     63                        objDict[hash]['type'] = self.determineType(objDict[hash], y) 
     64                    # Add to all files 
     65                    id = self.createIdFromFile(y) 
     66                    objDict[hash]['id'] = id 
     67                    if not (objDict[hash].has_key('title') and objDict[hash]['title']): 
     68                        objDict[hash]['title'] = id 
     69                    objDict[hash]['path'] = self.createPathFromFile(y) 
    5670 
    57                     if reshref == file or len(files) == 1: 
    58                         hashref = resourceid 
    59                         objDict[hashref] = resdata 
    60              
    61   
    62                         # Check if item is in organizations section 
    63                         orgs = [org for org in orgdata if org] 
    64                         if hashref in orgs: 
    65                             objDict[hashref]['excludeFromNav'] = False 
    66                             objDict[hashref]['title'] = orgdata[hashref] 
    67                         else: 
    68                             objDict[hashref]['excludeFromNav'] = True 
    69  
    70                     else: 
    71                         hashref = '%s%s' %(resourceid, file) 
    72                         objDict[hashref] = {} 
    73                         objDict[hashref]['excludeFromNav'] = True 
    74  
    75                     self.parseFile(context, file, objDict, hashref, id, path) 
    76                     if objDict[hashref]['type'] == 'Link': 
    77                         path_to_file = objDict[hashref]['file'] 
    78                         objDict['remoteUrl'] = cpresourcereader.readLink(source.readFile(path_to_file)) 
    79          
    8071        objcreator = getUtility(IIMSObjectCreator) 
    8172        objcreator.createObjects(objDict, context, source) 
    82         return 
    83  
    84  
    85  
    86  
    87  
  • collective.imstransport/trunk/collective/imstransport/utilities/imscp/imscpwriter.py

    r197 r306  
    44from collective.imstransport.utilities.imscp.cpwriter import CPWriter 
    55from collective.imstransport.utilities.imscp.cpresourcewriter import CPResourceWriter 
    6 from collective.imstransport.utilities.imsinterchange import IMSInterchangeWriter 
     6from collective.imstransport.utilities.imsinterchange import IMSWriter 
    77from collective.imstransport import IMSTransportMessageFactory as _ 
    88 
    9 IMS_schema = 'IMS Content Package' 
    10 IMS_version = '1.2' 
    11 LOM_version = 'LOMv1.0' 
    12 LOM_namespace = 'http://www.imsglobal.org/xsd/imsmd_v1p2' 
    13  
    14 class IMSCPWriter(IMSInterchangeWriter): 
     9class IMSCPWriter(IMSWriter): 
    1510    """ Write an IMS content package manifest file. """ 
    16  
    17     name = _(u'IMS Content Package') 
    1811 
    1912    def createPackage(self, filename, context): 
    2013        """ Creates an IMS Package """ 
    2114 
    22         self.context = context 
     15        destination = ZipfileWriter(context, file) 
    2316 
     17        cpw = CPWriter() 
    2418 
    25         namespaces = [('xmlns', 'http://www.imsglobal.org/xsd/imscp_v1p1'), 
    26                       ('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'),] 
    27         schema_locations = ['http://www.imsglobal.org/xsd/imscp_v1p1 http://www.imsglobal.org/xsd/imscp_v1p2.xsd',] 
    28          
    29         self.destination = ZipfileWriter(context,filename) 
    30         cpwriter = CPWriter(context) 
    31         cpwriter.writeManifestNode(self._createPathId(context.virtual_url_path(), 'MAN'), 
    32                                    context.ModificationDate(), 
    33                                    namespaces, 
    34                                    schema_locations) 
     19        # Create the Manifest 
     20        manId = self._createPathId(context.virtual_url_path(), 'MAN') 
     21        manVer = context.ModificationDate() 
     22        doc = cpw.createManifest(manId, manVer) 
     23 
     24        # Add top level metadata 
    3525        lang = context.Language() 
    3626        if not lang: 
    3727            lang = context.portal_properties.site_properties.getProperty('default_language') 
    38         cpwriter.writeLOMCPMetadata(context.getId(), context.Title(), context.portal_url(), IMS_schema, IMS_version, lang, context.Description(), context.Subject()) 
     28        cpw.writeTopLevelMetadata(doc, 
     29                                  context.getId(), 
     30                                  context.Title(), 
     31                                  context.portal_url(), 
     32                                  lang, 
     33                                  context.Description(), 
     34                                  context.Subject()) 
    3935 
    40         cpwriter.writeOrganizationsNode(self._createPathId(context.virtual_url_path(), 'ORG')) 
     36        # Write Organizations and Resources 
     37        orgId = self._createPathId(context.virtual_url_path(), 'ORG') 
     38        orgs = cpw.createOrganizations(doc, orgId) 
     39        res = cpw.createResources(doc) 
    4140 
    42         cpwriter.writeResources() 
     41        if orgs and res: 
     42            objs = self._getAllObjects(context) 
     43            for obj in objs: 
     44                # Need to consider excluding folders 
     45                # Get resource info 
     46                path = self._getObjectPath(obj, context) 
     47                vpath = obj.virtual_url_path() 
     48                refid = self._createPathId(vpath, 'RES') 
     49                # Check if we need to add to the organizations section 
     50                if not obj.getExcludeFromNav(): 
     51                    itemId = self._createPathId(vpath, 'ITM') 
     52                    cpw.writeItem(orgs, itemId, refid, obj.title) 
     53                rn = cpw.writeResource(res, refid, obj.Type(), path) 
    4354 
     55                id = obj.getId() 
     56                title = obj.Title() 
     57                urlbase = obj.portal_url() 
     58                lang = obj.Language() 
     59                if not lang: 
     60                    lang = obj.portal_properties.site_properties.getProperty('default_language') 
     61                desc = obj.Description() 
     62                kw = obj.Subject() 
     63                creators = obj.Creators()  
     64                contrib = obj.Contributors() 
     65                mod = obj.ModificationDate() 
     66                email = obj.portal_url.getPortalObject().getProperty('email_from_address') 
     67                format = obj.Format() 
     68                size = self.getObjSize(obj) 
     69                location = obj.renderBase() 
     70                value = 'yes' 
     71                rights_holder = obj.portal_properties.site_properties.getProperty('rights_holder') 
     72                rights_holder_email = obj.portal_properties.site_properties.getProperty('rights_holder_email') 
     73                copyright = self._getCopyrightString(obj.Rights(), rights_holder, rights_holder_email) 
     74                 
     75                md = cpw.createResourceMetadata(rn) 
     76                cpw.writeGeneralNode(md, id, title, 'en', desc, kw) 
     77                cpw.writeLifeCycleNode(md, creators, contrib, mod, None) 
     78                cpw.writeMetaMetadataNode(md, id, urlbase, email, mod, None, contrib) 
     79                cpw.writeTechnicalNode(md, format, size, location) 
     80                cpw.writeRightsNode(md, value, copyright, None) 
    4481 
    45         objects = self._getAllObjects(context) 
     82                if obj.Type() == 'Link': 
     83                    link = cpw.getLinkXml(title, obj.getRemoteUrl()) 
     84                    rpath = '%s' %path 
     85                    self._writeObjectData(link, rpath, destination) 
     86                    cpw.writeResourceFile(rn, rpath) 
     87                else: 
     88                    self._writeObjectData(obj, path, destination) 
     89                    cpw.writeResourceFile(rn, path) 
    4690 
    47         for object in objects: 
    48             path = self._getObjectPath(object, context) 
    49             itemId = self._createPathId(object.virtual_url_path(), 'ITM') 
    50             refId = self._createPathId(object.virtual_url_path(), 'RES') 
     91        self._writeObjectData(cpw.getManifest(doc), 'imsmanifest.xml', destination) 
    5192 
    52             if not object.isPrincipiaFolderish or getattr(object, 'getText', None): 
    53                 if not object.getExcludeFromNav(): 
    54                     cpwriter.writeItem(itemId, object.title, refId) 
    55  
    56                 path = self._getObjectPath(object, context) 
    57                 rlomwriter = CPResourceWriter(cpwriter) 
    58                 rlomwriter.writeResource(refId, 'webcontent', path) 
    59                 rlomwriter.writeLOMMetadata() 
    60                 rlomwriter.writeLOMNode(LOM_namespace) 
    61  
    62                 lang = object.Language() 
    63                 if not lang: 
    64                     lang = context.portal_properties.site_properties.getProperty('default_language') 
    65                     if not lang: 
    66                         lang = "x-none" 
    67  
    68                 rlomwriter.writeGeneralNode(object.getId(), object.Title(), object.portal_url(), lang, object.Description(), object.Subject()) 
    69  
    70                 rlomwriter.writeLifeCycleNode(object.Creators(), object.Contributors(), object.ModificationDate(), lang) 
    71  
    72                 email = object.portal_url.getPortalObject().getProperty('email_from_address') 
    73  
    74                 date = object.ModificationDate().decode('utf-8') 
    75                 contributors = object.Contributors() 
    76  
    77                 rlomwriter.writeMetaMetadata(object.id, object.portal_url(), email, date, LOM_version, lang, contributors) 
    78                 rlomwriter.writeTechnical(object.Format(), self.getObjSize(object), object.renderBase()) 
    79                 rights_holder = object.portal_properties.site_properties.getProperty('rights_holder') 
    80                 rights_holder_email = object.portal_properties.site_properties.getProperty('rights_holder_email') 
    81                 rlomwriter.writeRights(LOM_version, 'yes', self._getCopyrightString(object.Rights(), rights_holder, rights_holder_email), lang) 
    82                 rlomwriter.writeCustomMetadata(object) 
    83  
    84                 rlomwriter.writeFileNode(path) 
    85                  
    86                 self._writeObjectData(object, path) 
    87  
    88         self._writeObjectData(cpwriter.getManifest(), 'imsmanifest.xml') 
    89  
    90         if self.destination: 
    91             return self.destination.getOutput() 
     93        if destination: 
     94            return destination.getOutput() 
    9295        else: 
    9396            return None, None 
Note: See TracChangeset for help on using the changeset viewer.