From: mike <svn...@pl...> - 2006-07-31 21:43:44
|
Author: mike Date: Mon Jul 31 21:43:40 2006 New Revision: 26567 Modified: CMFBibliographyAT/trunk/migrations/cmfbib08to09.py Log: added more migration code for 0.8 -> 0.9 (1) test if the ImportCriteriasManager needs an upgrade, if so: 'publication_type' -> 'reference_type' (means bibref_item.meta_type) 'type' -> 'publication_type' (means new typeField id) (2) updateSchema of typeField o get old typeField values (id='type'), o store it in new typeField o delete the old 'type' attribute from the object Modified: CMFBibliographyAT/trunk/migrations/cmfbib08to09.py ============================================================================== --- CMFBibliographyAT/trunk/migrations/cmfbib08to09.py (original) +++ CMFBibliographyAT/trunk/migrations/cmfbib08to09.py Mon Jul 31 21:43:40 2006 @@ -4,11 +4,19 @@ # CMF imports from Products.CMFCore.utils import getToolByName +# Archetypes import +from Products.Archetypes.public import listTypes +from Products.Archetypes.utils import shasattr + # Product imports from Products.CMFBibliographyAT.config import REFERENCE_TYPES +from Products.CMFBibliographyAT.config import FOLDER_TYPES as BIBFOLDER_TYPES from Products.CMFBibliographyAT.tool.parsers.citationmanager import \ CitationManagerParser + +from Products.CMFBibliographyAT.content.fields import typeField +import copy class Migration(object): """Migrate from 0.8 to 0.9 @@ -25,20 +33,203 @@ def migrate(self): """Run migration on site object passed to __init__. """ - print >> self.out, u"Migrating CMFBibliographyAT 0.8 -> 0.9" + print >> self.out + print >> self.out, u"Migrating CMFBibliographyAT 0.8 -> 0.9" bibtool = getToolByName(self.site, 'portal_bibliography') self.migrateTool(bibtool) + #self.removePublicationTypeAttribute() + if self.needsCriteriasManagerUpgrade(): + self.migrateCriteriasManagerReferenceType() + if self.needsTypeFieldSchemaUpgrade(): + self.migrateTypeFieldSchema() def migrateTool(self, bibtool): """Migrate the bibtool. """ # Check for and add a persistent dictionary to keep track of # registered reference types on the tool. + print >> self.out, u'BibliographyTool migration:' + print >> self.out, u'---------------------------' rt = getattr(bibtool, '_reference_types', None) if rt is None: - msg = u"Adding the tool's _reference_types attribute." + msg = u" Adding the tool's _reference_types attribute." print >> self.out, msg bibtool._reference_types = PersistentMapping() # By default, we just use the standard CMFBib ref types for ref_type in REFERENCE_TYPES: bibtool._reference_types[ref_type] = None + else: + print >> self.out, u' Tool is up-to-date' + print >> self.out + + def needsCriteriasManagerUpgrade(self): + + """Check for old publication_type (alias for meta_type) Criterias in BibFolders' CriteriasManager + -> should be renamed to "reference_type" + """ + print >> self.out, u'ImportCriteriasManager schema migration:' + print >> self.out, u'----------------------------------------' + ct = getToolByName(self.site, 'portal_catalog') + bibtool = getToolByName(self.site, 'portal_bibliography') + + # only check ref_types without typeField (id: publication_type) + # if other ref_types have publication_type in ImportCriteriasManager + # then we definitely need to upgrade!!! + ReferenceClasses_without_typeField = [ t['klass'] for t in listTypes() if (t['meta_type'] in bibtool.getReferenceTypes()) and ('publication_type' not in [ field.getName() for field in t['schema'].fields() ]) ] + ReferenceTypes_without_typeField = tuple([ klass.meta_type for klass in ReferenceClasses_without_typeField ]) + + count = 0 + brains = ct(portal_type=BIBFOLDER_TYPES) + for brain in brains[:5]: + bibfolder = brain.getObject() + sel_crits = bibfolder.getSelectedCriterias() + for ref_type in sel_crits.keys(): + if (ref_type in ReferenceTypes_without_typeField) and ('publication_type' in sel_crits[ref_type]): + count += 1 + + if count: + print >> self.out, u' Upgrade of ImportCriteriasManager required.' + return True + + print >> self.out, u' No ImportCriteriasManager upgrade needed.' + print >> self.out + return False + + def migrateCriteriasManagerReferenceType(self): + + ct = getToolByName(self.site, 'portal_catalog') + bibtool = getToolByName(self.site, 'portal_bibliography') + brains = ct(portal_type=BIBFOLDER_TYPES) + + ReferenceClasses_without_typeField = [ t['klass'] for t in listTypes() if (t['meta_type'] in bibtool.getReferenceTypes()) and ('publication_type' not in [ field.getName() for field in t['schema'].fields() ]) ] + ReferenceTypes_without_typeField = tuple([ klass.meta_type for klass in ReferenceClasses_without_typeField ]) + + for brain in brains: + bibfolder = brain.getObject() + + # reinitialize a bibfolder's possible import criterias for each reference type + bibfolder.initCriterias() + print >> self.out, u' Migrating import criteria for BibliographyFolder: %s' % (bibfolder.getId()) + sel_crits = copy.deepcopy(bibfolder.getSelectedCriterias()) + + all_crits = {} + for ref_type, crits in copy.deepcopy(bibfolder.allCriterias()): + all_crits[ref_type] = crits + + for ref_type in sel_crits.keys(): + + # publication_type always migrate for classes with no typeField + # and if there is only one publication_type in the list + if ref_type in ReferenceTypes_without_typeField: + if 'publication_type' in sel_crits[ref_type]: + del sel_crits[ref_type][sel_crits[ref_type].index('publication_type')] + if ('reference_type' not in sel_crits[ref_type]) and ('reference_type' in all_crits[ref_type]): + sel_crits[ref_type].append('reference_type') + + # classes with typeField: migrate only if old type value still in dict + # or if publication_type appears twice in the list. + if ref_type not in ReferenceTypes_without_typeField: + + # if the refitem schema is already migrated (who knows why...) we have to seek + # for criteria lists that have two publication_type entries + more_than_one_publication_type = ( 1 < len([ field for field in bibfolder.allCriterias() if field == 'publication_type' ]) ) + + if ('type' in sel_crits[ref_type]) or more_than_one_publication_type: + + if 'publication_type' in sel_crits[ref_type]: + + # this will delete only one publiation_type entry + del sel_crits[ref_type][sel_crits[ref_type].index('publication_type')] + if ('reference_type' not in sel_crits[ref_type]) and ('reference_type' in all_crits[ref_type]): + sel_crits[ref_type].append('reference_type') + + if 'type' in sel_crits[ref_type]: + del sel_crits[ref_type][sel_crits[ref_type].index('type')] + if ('publication_type' not in sel_crits[ref_type]) and ('publication_type' in all_crits[ref_type]): + sel_crits[ref_type].append('publication_type') + + else: + + if 'publication_type' in sel_crits[ref_type]: + del sel_crits[ref_type][sel_crits[ref_type].index('publication_type')] + if ('reference_type' not in sel_crits[ref_type]) and ('publication_type' in all_crits[ref_type]): + sel_crits[ref_type].append('reference_type') + + #print 'Migrating criterias of BibFolder: %s' % bibfolder.getId() + #print sel_crits + bibfolder.setCriterias(sel_crits) + print >> self.out + + def needsTypeFieldSchemaUpgrade(self): + """Check for old straying type field remnants, they indicate a typeField migration need + """ + print >> self.out, u'typeField schema migration:' + print >> self.out, u'---------------------------' + ct = getToolByName(self.site, 'portal_catalog') + bibtool = getToolByName(self.site, 'portal_bibliography') + + # detect reference_types that contain the typeField + ReferenceClasses_with_typeField = [ t['klass'] for t in listTypes() if (t['meta_type'] in bibtool.getReferenceTypes()) and ('publication_type' in [ field.getName() for field in t['schema'].fields() ]) ] + ReferenceTypes_with_typeField = tuple([ klass.meta_type for klass in ReferenceClasses_with_typeField ]) + + brains = ct(portal_type=ReferenceTypes_with_typeField) + # check ALL(!) brains if we really need schema upgrade for old typeField: 'type' -> 'publication_type' + for brain in brains: + old_typeField_value = getattr(brain.getObject(), 'type', False) + + # to avoid mismatch with the BaseObject's type definition (alias for schema) check + # for a unicode value in typeField + if old_typeField_value and (type(old_typeField_value) == type(u'')): + print >> self.out, u' Upgrade of typeField required.' + return True + + print >> self.out, u' No typeField schema upgrade needed.' + print >> self.out + return False + + def migrateTypeFieldSchema(self): + """Migrate typeField id 'type' to new (less overloaded) id 'publication_type' + """ + ct = getToolByName(self.site, 'portal_catalog') + bibtool = getToolByName(self.site, 'portal_bibliography') + + # detect reference_types that contain the typeField + ReferenceClasses_with_typeField = [ t['klass'] for t in listTypes() if (t['meta_type'] in bibtool.getReferenceTypes()) and ('publication_type' in [ field.getName() for field in t['schema'].fields() ]) ] + ReferenceTypes_with_typeField = tuple([ klass.meta_type for klass in ReferenceClasses_with_typeField ]) + + brains = ct(meta_type=ReferenceTypes_with_typeField) + for brain in brains: + + bibref_item = brain.getObject() + # this one is the old typeField value + old_typeField_value = copy.deepcopy(getattr(bibref_item, 'type', False)) + print + print 'HALLO!!!!!!!!!!!!!!: %s' % old_typeField_value + print + # this one the new typeField with id 'publication_type' + new_typeField = bibref_item.Schema().get('publication_type', None) + + # if there is no formerly set typeField value, just do the schema update + if new_typeField and (type(old_typeField_value) == type(bibref_item.schema)): + print >> self.out, u' Only simple schema update needed for ObjectId: %s - typeField value: %s.' % (bibref_item.getId(), bibref_item.getPublication_type()) + bibref_item._updateSchema() + + # but if there is an old 'type' attribute in the bibref_item object, update the new typeField with its value + # to avoid mismatch with the BaseObject's type definition (alias for schema) check for a unicode value in typeField + elif new_typeField and (type(old_typeField_value) == type(u'')): + print + print 'HALLO before del !!!!!!!!!!!!!!: %s' % old_typeField_value + print + delattr(bibref_item, 'type') + print + print 'HALLO after del!!!!!!!!!!!!!!: %s' % old_typeField_value + print + bibref_item._updateSchema() + bibref_item.edit(publication_type=old_typeField_value) + print >> self.out, u' Migrating typeField of ObjectId %s: value=\'%s\'' % (brain.getId, bibref_item.getPublication_type()) + + else: + + print >> self.out, u' typeField schema update for ObjectId: %s failed.' % bibref_item.getId() + + print >> self.out |