Logo Search packages:      
Sourcecode: zope-cmfbibliographyat version File versions  Download package

base.py

##########################################################################
#                                                                        #
#           copyright (c) 2003, 2005 ITB, Humboldt-University Berlin     #
#           written by: Raphael Ritz, r.ritz@biologie.hu-berlin.de       #
#                                                                        #
##########################################################################

"""BaseEntry: base class for bibliographic references;
defines the common schema elements and provides some
basic functionality """

from DateTime import DateTime
from Acquisition import aq_base
from ComputedAttribute import ComputedAttribute
from AccessControl import ClassSecurityInfo
from Products.CMFCore.permissions import View, ModifyPortalContent
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.utils import getToolByName

from Products.Archetypes.public import BaseContent, DisplayList

from Products.CMFBibliographyAT.interfaces import IBibliographyExport

from Products.CMFBibliographyAT.content.schemata \
    import HeaderSchema, AuthorSchema, CoreSchema, TrailingSchema

BaseEntrySchema = HeaderSchema + \
                  AuthorSchema + \
                  CoreSchema + \
                  TrailingSchema

00032 class BaseEntry(BaseContent):
    """Base content for bibliographical references content types
    """
    global_allow = 0
    content_icon = 'ref_icon.png'

    schema = BaseEntrySchema

    __implements__ = (BaseContent.__implements__,
                      IBibliographyExport,
                     )
    security = ClassSecurityInfo()
    
    actions = (
        {'id'           : 'view',
         'name'         : 'View',
         'action'       : 'string:${object_url}/bibliography_entry_view',
         'permissions'  : (View,),
         'category'     : 'object',
         },
        )

    # the default source
    security.declareProtected(View, 'Source')
00056     def Source(self):
        """
        the default source format
        """
        try:
            source = self.DefaultSource()
        except AttributeError:   # don't blow if we have no skin context
            source = self.portal_type
        return source


    # enable field sharing between 'abstract' and 'description'
    security.declareProtected(View, 'getAbstract')
00069     def getAbstract(self, **kw):
        """ get the 'description' and put it in the 'abstract'
        """
        return self.Description()
    
    security.declareProtected(ModifyPortalContent, 'setAbstract')
00075     def setAbstract(self, val, **kw):
        """ synchronize 'abstract' and 'description'
        """
        self.setDescription(val)

    # helper method for direct attribute access
    # !! Should not be called anymore since Archetypes
    # !! builds automatic getFieldName() methods
    # rr: still needed by the bibtex renderer

00085     def getFieldValue(self, field_name):
        """
        get a field's value
        """
        field = self.getField(field_name)
        value = getattr(self, field.accessor)()
        if value:
            return value
        else:
            try:
                return field.getDefault()
            except TypeError:
                # AT1.3 compliant
                return field.getDefault(self)

    # custom methods for author handling
    security.declareProtected(View, 'getAuthorList')
00102     def getAuthorList(self):
        """
        returns the list of author dictionaries for editing
        assumes attribute storage for authors

        Deprecated; use default accessor instead
        """
        return self.getAuthors()

    security.declareProtected(View, 'Authors')
00112     def Authors(self, *args, **kwargs):
        """Alias for the publication author's accessor
        with a custom default format ("%L, %f%m") if not specified"""
        if 'format' not in kwargs.keys():
            kwargs['format'] = "%L, %f%m"
        return self.getAuthors()(*args, **kwargs)

    security.declareProtected(View, 'getAuthorURL')
00120     def getAuthorURL(self, author):
        """
        finds the URL of the author's hompage
        First, looks if 'homepage' is set in the 'author' dictionary
        Second, asks the tool for an entry for 'firstname' + 'lastname'
        Third, asks the membership tool whether there is a user 'lastname'
        """
        # 1. on object base
        homepage = author.get('homepage', None)
        if homepage: return homepage

        # 2. on bibfolder base
        parent = self.aq_parent
        full_name = author.get('firstname', '') \
                    + ' ' \
                    + author.get('lastname', '')

        if parent.meta_type == 'BibliographyFolder':
            homepage = parent.AuthorURLs().get(full_name.strip(), None)
        if homepage: return homepage

        # 3. Site wide look-up by fullname
        membertool = getToolByName(self, 'portal_membership', None)
        full_names = [m.getProperty('fullname', 'dummy') \
                      for m in membertool.listMembers()]
        try:
            index = full_names.index(full_name)
            user = membertool.listMembers()[index].getId()
            return membertool.getHomeUrl(user, 1)
        except ValueError:
            pass

        # 4. Site wide look-up by first initial plus lastname

        fname = author.get('firstname', '')
        lname = author.get('lastname', '')
        abbrev_name = ''
        if fname: abbrev_name += fname + ' '
        abbrev_name += lname
        abbrev_name = abbrev_name.strip()

        abbrev_names = []
        for name in full_names:
            tokens = name.split()
            if len(tokens) > 1:
                aname = tokens[0][0] + ' ' + tokens[-1]
            else:
                aname = name
            abbrev_names.append(aname)
        try:
            index = abbrev_names.index(abbrev_name)
            user = membertool.listMembers()[index].getId()
            return membertool.getHomeUrl(user, 1)
        except ValueError:
            pass


        # 5. admittedly stupid default
        user = author.get('lastname', '').lower()
        homepage = membertool.getHomeUrl(user, 1)

        return homepage

    security.declareProtected(View, 'getURL')
00184     def getURL(self, defaultURL=None):
        """
        the publication_url if set, otherwise a link to PubMed
        if pmid is set or the default otherwise
        """
        url = self.getPublication_url()
        if url:
            return url
        else:
            return defaultURL

    security.declareProtected(View, 'PMID')
00196     def PMID(self):
        """
        to be available for all types
        overwritten by article
        """
        return None

    security.declareProtected(View, 'ISBN')
00204     def ISBN(self):
        """
        to be available for all types
        overwritten by books
        """
        return None

    def pre_validate(self, REQUEST, errors):
        authors = REQUEST.get('authors',[])
        result = []
        references=[]
        for author in authors:
            reference = author.get('reference', None)
            if reference == 'None':
                author.reference = ''
            elif reference:
                references.append(reference)
                if not author.get('lastname', None):
                    firstnames, lastname = self._name_from_reference(reference)
                    author.firstnames = firstnames
                    author.lastname = lastname
            if ''.join(author.values()).strip():
                result.append(author)
        REQUEST.form['authors'] = result[:]
        REQUEST.form['member_publication_authors'] = references[:]

    def _name_from_reference(self, uid):
        catalog = getToolByName(self, 'uid_catalog', None)
        if catalog is None:
            return ('','')
        brains = catalog(UID=uid)
        if not brains:
            return ('','')
        parts = brains[0].Title.split()
        first = ''.join(parts[:-1]).strip()
        last = parts[-1]
        return first, last

    # try to set author references, e.g., after uploads
    security.declareProtected(ModifyPortalContent, 'inferAuthorReferences')
00244     def inferAuthorReferences(self, report_mode='v'):
        """
        If the item has no author references set but the tool suppors
        member referencesw or the site
        uses CMFMember, it tries to find a content object croresponding
        to the author name and makes reference there.
        
        Lookup is done on firstname lastname match.
        
        A report is returned controlled by the mode:

        - 'v': verbose; the default; for each author it is indicated
               what was done.
        - 'q': quiet; nothing is returned
        - 'c': conflicts only; conflicts occur if several potential
               target members are found
        """
        if not self.showMemberAuthors() or \
               self.usesCMFMember()or \
               self.getMember_publication_authors():
            return "No inference attempted"
        report = []
        authors = []
        a_modified = False
        md = getToolByName(self, 'portal_memberdata')
        bib_tool = getToolByName(self, 'portal_bibliography')
        membertypes = bib_tool.getProperty('member_types') or \
                      md.getAllowedMemberTypes()
        catalog = getToolByName(self, 'portal_catalog')
        for author in self.getAuthors():
            authors.append(author)
            last = author.get('lastname', None)
            if last is None:
                continue
            candidates = catalog(portal_type=membertypes,
                                 Title=last)
            if not candidates:
                msg = "%s: no corresponding member found." % author()
                if report_mode == 'v':
                    report.append(msg)
            elif len(candidates) > 1:
                msg = "%s: several corresponding members found:" % author()
                for c in candidates:
                    msg += " %s at %s," % (c.Title, c.getURL(relative=1))
                report.append(msg)
            else:
                target = candidates[0].getObject()
                name = target.Title()
                if not name.startswith(author.get('firstname')) \
                   or not name.endswith(author.get('lastname')):
                    msg = "%s: no corresponding member found." % author()
                    continue
                self.addReference(target, 'authorOf')
                author['reference'] = target.UID()
                a_modified = True
                msg = "%s: referring to %s at %s." \
                      % (author(),
                         name,
                         target.absolute_url(relative=1),
                         )
                if report_mode == 'v':
                    report.append(msg)
        if a_modified:
            self.setAuthors(authors)
        if report_mode != 'q' and report:
            ## report.insert(0, "%s:\n" % self.absolute_url(relative=1))
            return ' '.join(report)
        return None

    security.declareProtected(View, 'getPublicationDate')
00314     def getPublicationDate(self):
        """
        Returns the publication date as DateTime
        or None if it is not well defined
        """
        year = self.getField('publication_year').get(self)
        try:
            year = int(year)
        except ValueError:
            year = None

        month = self.getField('publication_month').get(self)
        if month:
            try:
                month = int(month)
            except ValueError:
                try:
                    # This is probably a string
                    monthcomp = month.split(' ')
                    month = 1
                    for m in monthcomp:
                        if m.lower() in DateTime._monthmap.keys():
                            month = m
                            continue
                except (ValueError, AttributeError, IndexError):
                    month = 1
        else:
            month = 1

        return year and DateTime('%s/%s/01' % (year, month)) or None

    publication_date = ComputedAttribute(getPublicationDate, 1)

    security.declareProtected(View, 'getMembers')
00348     def getMembers(self):
        """
        For use when members are authors, return a DisplayList of members
        """
        value = DisplayList()
        value.add('', '<no reference>')
        if self.showMemberAuthors():
            md = getToolByName(self, 'portal_memberdata')
            membertypes = md.getAllowedMemberTypes()
            catalog = getToolByName(self, 'portal_catalog')
            results = catalog(portal_type=membertypes)
            for r in results:
                uid = getattr(aq_base(r), 'UID', r.getObject().UID())
                title = r.Title or r.id
                value.add(uid, title)
        return value

    security.declareProtected(View, 'getSiteMembers')
00366     def getSiteMembers(self, *args, **kw):
        """
        For use when members are authors, return a DisplayList of members
        Alternative to 'getMembers' if 'no reference' must not be empty
        (to work around a bug in the 'Records' packager)
        """
        value = DisplayList()
        value.add('None', 'Select or specify')
        if self.showMemberAuthors():
            bib_tool = getToolByName(self, 'portal_bibliography')
            membertypes = bib_tool.getProperty('member_types')
            sort_on = bib_tool.getProperty('sort_members_on', 'getId')
            catalog = getToolByName(self, 'portal_catalog')
            results = catalog(portal_type=membertypes,
                              sort_on=sort_on)
            for r in results:
                uid = getattr(aq_base(r), 'UID', r.getObject().UID())
                title = r.Title or r.id
                value.add(uid, title)
        elif self.usesCMFMember():   # BBB
            md = getToolByName(self, 'portal_memberdata')
            membertypes = md.getAllowedMemberTypes()
            catalog = getToolByName(self, 'portal_catalog')
            results = catalog(portal_type=membertypes,
                              sort_on='getId')
            for r in results:
                uid = getattr(aq_base(r), 'UID', r.getObject().UID())
                title = r.Title or r.id
                value.add(uid, title)
        return value

    security.declareProtected(View, 'showMemberAuthors')
    def showMemberAuthors(self):
        bib_tool = getToolByName(self, 'portal_bibliography')
        return bib_tool.getProperty('support_member_references')

    security.declareProtected(View, 'usesCMFMember')
    def usesCMFMember(self):
        quickinstaller = getToolByName(self, 'portal_quickinstaller')
        return quickinstaller.isProductInstalled('CMFMember')

    security.declareProtected(ModifyPortalContent,
                              'setMemberPublicationAuthors')
00409     def setMemberPublicationAuthors(self, value, **kw):
        """Default Mutator."""
        if kw.has_key('schema'):
            schema = kw['schema']
        else:
            schema = self.Schema()
            kw['schema'] = schema
        schema['member_publication_authors'].set(self, value, **kw)
        self.updateMemberPublicationAuthors()

    security.declareProtected(ModifyPortalContent,
                              'updateMemberPublicationAuthors')
    def updateMemberPublicationAuthors(self):
        authors = self.Schema()['member_publication_authors'].get(self, aslist=1)
        mpa = []
        for author in authors:
            data = self.getAuthorDataFromMember(author)
            if data is not None:
                mpa.append(data)
        self.member_publication_authors_cache = mpa


    # support inline citations
    security.declareProtected(View, 'citationLabel')    
00433     def citationLabel(self, join_two='and', et_al='et al.'):
        """
        a short label for inline citations like
        "Ritz, 1995" or "Ritz and Herz, 2004" or
        "Ritz et al., 2005"
        """
        authors = self.getAuthorList()
        nofa = len(authors)
        year = self.getField('publication_year').get(self)

        if nofa == 0:
            return "Anonymous, %s" % year

        if nofa == 1:
            return "%s, %s" % (authors[0].get('lastname', ''),
                               year)        
        if nofa == 2:
            return "%s %s %s, %s" % (authors[0].get('lastname', ''),
                                     join_two,
                                     authors[1].get('lastname', ''),
                                     year)
        return "%s %s, %s" % (authors[0].get('lastname', ''),
                              et_al,
                              year) 

Generated by  Doxygen 1.6.0   Back to index