[Commits] (jeffrey) Modifed Importer code to read its mapping transform from an XML file.

commits at osafoundation.org commits at osafoundation.org
Fri Apr 23 17:09:30 PDT 2004


Commit by: jeffrey
Modified files:
osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/ImportMap.py None 1.1
osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/MapXML.py None 1.1
osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/outlook2000.xml None 1.1
osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py 1.2 1.3
osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py 1.2 1.3

Log message:
Modifed Importer code to read its mapping transform from an XML file.


ViewCVS links:
http://cvs.osafoundation.org/index.cgi/osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/ImportMap.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/MapXML.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/outlook2000.xml?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3
http://cvs.osafoundation.org/index.cgi/osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3

Index: osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py
diff -u osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py:1.2 osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py:1.3
--- osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py:1.2	Mon Mar  8 09:29:45 2004
+++ osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/Importer.py	Fri Apr 23 17:08:59 2004
@@ -1,49 +1,29 @@
 """Base class for Chandler Importer objects."""
 
-__revision__  = "$Revision: 1.2 $"
-__date__      = "$Date: 2004/03/08 17:29:45 $"
+__revision__  = "$Revision: 1.3 $"
+__date__      = "$Date: 2004/04/24 00:08:59 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
 import application.Globals as Globals
+import csv
 
 class Importer:
     """Base class for Chandler Importer objects.
     
     @ivar lineNumber: Current line number in the source file.
-    @ivar _destination: The parent object for objected that are imported.
+    @ivar destination: The parent object for objects that are imported.
+    @ivar source: The filesystem path for the file that should be imported
+    @ivar mapping: An L{ImportMap.ImportMap} object
     
     """
     def __init__(self, destination=None):
-        self.setDestination(destination)
+        if destination == None:
+            self.destination=Globals.repository.find("//userdata/contentitems")
+        else:
+            self.destination=Globals.repository.find(destination)
         self.lineNumber=0
     
-    def setDestination(self, spec=None):
-        """Set where in the repository items should be imported to.
-        
-        @param spec: The parent for items created when importing.
-                     C{//userdata/contentitems} is the default.
-        @type spec: a Path, UUID, or string that can be coerced into a Path or
-                    UUID.
-                    
-        """
-        if spec is None:
-            self._destination=Globals.repository.find("//userdata/contentitems")
-        else:
-            self._destination=Globals.repository.find(spec)
-            
-    def getDestination(self):
-        """Return the parent for imported items."""
-        return self._destination
-    
-    def setSourcePath(self, path):
-        """Set the filesystem path pointing to the file to be imported."""
-        self._source=path
-        
-    def getSourcePath(self):
-        """Get the filesystem path for the file that should be imported."""
-        return self._source
-            
     def processObjects(self, sourceFile):
         """Abstract method to process the source file.
         
@@ -55,53 +35,104 @@
         @raise CreationError: If the item can't be created in the repository
         
         Concrete implementations should read sourceFile, raising a
-        C{FormatError} if the file isn't formatted as expected.
+        L{FormatError} if the file isn't formatted as expected.
         Implementations that expect text files as input should increment
         lineNumber every time they read a line of text so that a more useful
-        C{FormatError} can be thrown.
+        L{FormatError} can be thrown.
         
         Once enough lines have been read to define an object, the method 
-        should create a Chandler object whose parent is C{_destination}
-        (retrieved via L{getDestination}).  If an object can't be created for
-        any reason, the method should catch any exceptions and throw a new
-        C{CreationError}.
+        should create a Chandler object whose parent is C{destination}.  If an
+        object can't be created for any reason, the method should catch any
+        exceptions and throw a new L{CreationError}.
         
-        If the file ends in the middle of reading in an object, a C{FormatError}
+        If the file ends in the middle of reading in an object, a L{FormatError}
         should be thrown.
         
         """
         pass
     
-    def massageObject(self, object):
-        """Massage recently created object.
+    def postProcess(self, object):
+        """Further process recently created object.
         
         @param object: Recently created object.
         
         Called by processFile after object creation.  Subclasses may override
-        this method to make minor changes to imported objects.
+        this method to make changes to imported objects and to create attributes
+        not defined in the mapping.
         
         """
         pass
 
     def processFile(self):
-        """Create objects in sourceFile, return the number of objects created.
+        """Create objects in sourceFile.
         
-        Throws FormatError, CreationError, and IOError.
+        return: The number of high-level objects created, each high level object
+        may have created many items as attributes.
+
+        Raises FormatError, CreationError, and IOError.
         
         """
         self.lineNumber=0
-        f=file(self.getSourcePath())
+        f=file(self.source)
         objects=0
         for object in self.processObjects(f):
-            self.massageObject(object)
+            self.postProcess(object)
             objects=objects + 1
         try:
             Globals.repository.commit()
         except:
-            raise CreationError, "Error commiting to repository"
+            raise CreationError, "Error commiting to repository",self.lineNumber
         f.close()
         return objects
 
+class CSVImporter(Importer):
+    """Base class for objects that import CSV files into the repository.
+    
+    @var dialect: The CSV dialect to be used when parsing files.
+    @type dialect: string
+    @var hasHeader: Whether or not the file's first line should be interpreted
+                    as a header, not as data.
+    @type hasHeader: boolean
+    @var keyList: The keys each column in the file should be associated with.
+    @type keyList: list of strings
+    
+    """
+    def __init__(self, hasHeader=True, dialect='excel', keyList=None, dest=None):
+        Importer.__init__(self, dest)
+        self.dialect=dialect
+        self.hasHeader=hasHeader
+        self.keyList=keyList
+    
+    def processObjects(self, file):
+        """Main iterator for importing objects from CSV.
+        
+        @see processObjects in L{Importer}.
+        
+        If C{hasHeader} is C{True}, use the first line of C{file} to determine
+        the column keys. Otherwise use keyList.
+        
+        """
+        try:
+            if self.hasHeader:
+                self.lineNumber=self.lineNumber + 1
+                header=iter([file.readline()])
+                self.keyList=(csv.reader(header).next())
+                reader = csv.DictReader(file, self.keyList,dialect=self.dialect)
+            else:
+                reader = csv.DictReader(file, self.keyList,dialect=self.dialect)
+            for row in reader:
+                self.lineNumber=self.lineNumber + 1
+                result=self.mapping.process(row)
+                if not result:
+                    raise DataError, \
+                        ("Mapping error at line %s of the import file" \
+                        % self.lineNumber)
+                else:
+                    yield result
+        except csv.Error, e:
+            raise FormatError,\
+                  ("Couldn't parse CSV file: %s" % str(e), self.lineNumber)
+
 class DataError(Exception):
     """Base class for exceptions when acquiring and processing external data."""
     pass
@@ -112,7 +143,7 @@
         self.message = message
         self.line = line
     def __str__(self):
-        if self.line is not None:
+        if self.line != None:
             return "At line %d: %s" % (line, message)
         else:
             return message
@@ -123,7 +154,7 @@
         self.message = message
         self.line = line
     def __str__(self):
-        if self.line is not None:
+        if self.line != None:
             return "At line %d: %s" % (self.line, self.message)
         else:
             return self.message

Index: osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py
diff -u osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py:1.2 osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py:1.3
--- osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py:1.2	Tue Mar 23 21:08:09 2004
+++ osaf/chandler/Chandler/parcels/OSAF/framework/utils/imports/OutlookContacts.py	Fri Apr 23 17:08:59 2004
@@ -1,194 +1,15 @@
 """Import contacts exported by Outlook to CSV format."""
 
-__revision__  = "$Revision: 1.2 $"
-__date__      = "$Date: 2004/03/24 05:08:09 $"
+__revision__  = "$Revision: 1.3 $"
+__date__      = "$Date: 2004/04/24 00:08:59 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
+import Importer, MapXML, os
 import application.Globals as Globals
-import CSVImporter
-import os
-import mx.DateTime as DateTime
-
-"""
-    Explanation for the mapping constant: @@@TODO
-"""
-
-TOP=1
-DATETYPE=2
-LISTTYPE=3
-CONCATTYPE=4
-CONDITIONALCONST=5
-
-TRANSLATIONMAP=\
-  (TOP, "//parcels/OSAF/contentmodel/contacts/Contact", 
-      {"contactName" : 
-          {"firstName" : "First Name",
-           "lastName" : "Last Name",
-           "middleName" : "Middle Name"},
-       "birthday" : (DATETYPE, "Birthday"),
-       "homeSection" :
-          {"spouse" : "Spouse",
-           "children" : (LISTTYPE, "Children"),
-           "webPages" : (LISTTYPE, "Web Page"),
-           "anniversary" : (DATETYPE, "Anniversary"),
-           "emailAddresses" : (LISTTYPE,
-              {"emailAddress" : "E-mail Address"},
-              {"emailAddress" : "E-mail 2 Address"},
-              {"emailAddress" : "E-mail 3 Address"}),
-           "streetAddresses" : (LISTTYPE,
-              {"streetAddress" : (CONCATTYPE, 
-                   "Home Street",
-                   "Home Street 2",
-                   "Home Street 3"),
-               "locality" : "Home City",
-               "region" : "Home State",
-               "postalCode" : "Home Postal Code",
-               "countryName" : "Home Country",
-               "postOfficeBox" : "PO Box"}),
-           "phoneNumbers" : (LISTTYPE,
-              {"phoneNumber" : "Home Phone",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Home Phone"))},
-              {"phoneNumber" : "Home Phone 2",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Home Phone 2"))},
-              {"phoneNumber" : "ISDN",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "isdn", "ISDN"))},
-              {"phoneNumber" : "Mobile Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "cell", "Mobile Phone"))},
-              {"phoneNumber" : "Home Fax",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "fax", "Home Fax"))},
-              {"phoneNumber" : "Car Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "car", "Car Phone"))},
-              {"phoneNumber" : "Other Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Other Phone"))},
-              {"phoneNumber" : "Pager",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "pager", "Pager"))},
-              {"phoneNumber" : "Primary Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Primary Phone"))})},
-       "workSection" :
-          {"employer" : "Company",
-           "jobTitle" : "Job Title",
-           "phoneNumbers" : (LISTTYPE,
-              {"phoneNumber" : "Business Phone",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Business Phone"))},
-              {"phoneNumber" : "Business Phone 2",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Business Phone 2"))},
-              {"phoneNumber" : "Business Fax",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "fax", "Business Fax"))},
-              {"phoneNumber" : "Company Main Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST,"voice","Company Main Phone"))}),
-           "streetAddresses" : (LISTTYPE,
-              {"streetAddress" : (CONCATTYPE, 
-                   "Business Street",
-                   "Business Street 2",
-                   "Business Street 3"),
-               "locality" : "Business City",
-               "region" : "Business State",
-               "postalCode" : "Business Postal Code",
-               "countryName" : "Business Country"})}})
-
-TRANSLATIONMAP_OLD=\
-  (TOP, "//parcels/OSAF/contentmodel/contacts/Contact", 
-      {"contactName" : 
-          {"firstName" : "First Name",
-           "lastName" : "Last Name",
-           "middleName" : "Middle Name"},
-       "birthday" : (DATETYPE, "Birthday"),
-       "homeSection" :
-          {"spouse" : "Spouse",
-           "children" : (LISTTYPE, "Children"),
-           "webPages" : (LISTTYPE, "Web Page"),
-           "anniversary" : (DATETYPE, "Anniversary"),
-           "emailAddresses" : (LISTTYPE,
-              {"emailAddress" : "E-mail Address"},
-              {"emailAddress" : "E-mail 2 Address"},
-              {"emailAddress" : "E-mail 3 Address"}),
-           "streetAddresses" : (LISTTYPE,
-              {"streetAddress" : (CONCATTYPE, 
-                   "Home Street",
-                   "Home Street 2",
-                   "Home Street 3"),
-               "locality" : "Home City",
-               "region" : "Home State",
-               "postalCode" : "Home Postal Code",
-               "countryName" : "Home Country",
-               "postOfficeBox" : "PO Box"}),
-           "phoneNumbers" : (LISTTYPE,
-              {"phoneNumber" : "Home Phone",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Home Phone"))},
-              {"phoneNumber" : "Home Phone 2",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Home Phone 2"))},
-              {"phoneNumber" : "ISDN",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "isdn", "ISDN"))},
-              {"phoneNumber" : "Mobile Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "cell", "Mobile Phone"))},
-              {"phoneNumber" : "Home Fax",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "fax", "Home Fax"))},
-              {"phoneNumber" : "Car Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "car", "Car Phone"))},
-              {"phoneNumber" : "Other Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Other Phone"))},
-              {"phoneNumber" : "Pager",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "pager", "Pager"))},
-              {"phoneNumber" : "Primary Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Primary Phone"))})},
-       "workSection" :
-          {"employer" : "Company",
-           "jobTitle" : "Job Title",
-           "phoneNumbers" : (LISTTYPE,
-              {"phoneNumber" : "Business Phone",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Business Phone"))},
-              {"phoneNumber" : "Business Phone 2",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST, "voice", "Business Phone 2"))},
-              {"phoneNumber" : "Business Fax",
-               "phoneType" :
-                   (LISTTYPE, (CONDITIONALCONST, "fax", "Business Fax"))},
-              {"phoneNumber" : "Company Main Phone",
-               "phoneType" : 
-                   (LISTTYPE, (CONDITIONALCONST,"voice","Company Main Phone"))}),
-           "streetAddresses" : (LISTTYPE,
-              {"streetAddress" : (CONCATTYPE, 
-                   "Business Street",
-                   "Business Street 2",
-                   "Business Street 3"),
-               "locality" : "Business City",
-               "region" : "Business State",
-               "postalCode" : "Business Postal Code",
-               "countryName" : "Business Country"})}})
 
-
-
-#Something should probably be done with the "Notes" field @@@TODO
-#Also deal with the special case of gender (enum){"gender" : "Gender"} @@@TODO
-
-#Why do some aspects not get exposed to python .aspectname access?  Or was this
-#just a problem with the phoneType cardinality?
-#Delete oddity
-#Should all Kinds offer a newItem method?
+#@@@TODO deal with the special case of gender (enum){"gender" : "Gender"}
+#Unspecified in Outlook, Unknown in Chandler
 
 """
         Importing Outlook CSV Contacts currently munges data in the following
@@ -203,180 +24,64 @@
         centric users) is ignored.
         * Children is treated as a single string, not parsed into multiple kids
         * E-mail Display Name is ignored.
-        * Title (Mr., Dr., etc.) is ignored. 
         * Suffix is ignored.
         * "Other" (beyond home and work) addresses are ignored.
         * See the list below for a complete list of fields that are ignored
+        * Gender isn't currently dealt with because enumeration mappings haven't
+        been implemented.
 
 currently ignored fields:
 
-"Title" "Suffix"        "Department"
+"Title" => not the same as jobTitle, things like "Prof.",  needed
+"Suffix" => needed
+"Department" => needed
+"Profession" => needed
+* Do other.
 "Other Street"        "Other Street 2"  "Other Street 3"        "Other City" "Other State"
-"Other Postal Code"   "Other Country"   "Assistant's Phone"   "Assistant's Name"
-"Telex"   "TTY/TDD Phone"   "Radio Phone" "Callback"                                        
-"Account" "Billing Information" "Categories"        "Directory Server"
-"E-mail Type"        "E-mail Display Name"        "E-mail 2 Type"        
-"E-mail 2 Display Name"        "E-mail 3 Type"        "E-mail 3 Display Name"
-"Government ID Number"        "Hobby"        "Initials"        "Internet Free Busy"
-"Keywords"        "Language"        "Location"        "Manager's Name"        "Mileage"
-"Office Location"        "Organizational ID Number"    "Priority"        "Private"
-"Profession"        "Referred By"        "Sensitivity"        "User 1"        "User 2"
-"User 3"        "User 4"
+"Other Postal Code"   "Other Country"
+"Assistant's Phone"   "Assistant's Name" => Assistant needed?
+"Manager's Name" => Manager needed?
+"Telex"   "TTY/TDD Phone"   "Radio Phone" "Callback" => what IS this?
+"Initials" => is initials entirely a derived field? can it just be ignored?                       
+
+"Categories" => semi-colon separated list of categories, some defined by Outlook, some by the user
+
+"Account" "Billing Information"
+"Directory Server" => NetMeeting server for the contact
+"E-mail Type" => SMTP or FAX or MSN or MSNINET, ignore "E-mail 2 Type" "E-mail 3 Type"  
+"E-mail Display Name" => ignore? "E-mail 2 Display Name" "E-mail 3 Display Name"
+"Government ID Number" "Organizational ID Number" => ?
+"Hobby" => ?
+"Internet Free Busy" => iCalendar server, probably should be used.
+"Keywords" => not exported, but in Outlook look identical to Categories, ignore
+"Language"
+"Location"
+"Office Location" 
+"Mileage" => Exists by default for all Outlook items, probably can be ignored
+"Priority" "Private"
+"Referred By"
+"Sensitivity"
+"User 1"        "User 2" "User 3"        "User 4"
 """
 
-class OutlookContacts(CSVImporter.CSVImporter):
+MAPPINGDIR="parcels/OSAF/framework/utils/imports"
+
+class OutlookContacts(Importer.CSVImporter):
     """Import contacts exported by Outlook to CSV format."""
-    def __init__(self, sourceFile=None, version="2000"):
+    def __init__(self, sourceFile=None, mapping="outlook2000.xml"):
         """Currently version is ignored, assumes Outlook 2000 format."""
-        CSVImporter.CSVImporter.__init__(self)        
+        Importer.CSVImporter.__init__(self)        
         if sourceFile is None:
             #hack to avoid user interface to input a file, os.getcwd()
             #will probably be the Chandler dir, but YMMV.
-            self.setSourcePath(os.path.join(os.getcwd(), "contacts.csv"))
-        else:
-            self.setSourcePath(sourceFile)
-
-    def createAttributes(self, parent, tree, importRowDict, kind):
-        """Populate parent's attributes.
-        
-        tree should be a dictionary whose keys are itemNames
-        of attributes of parent.  Attributes of the appropriate Kind are created
-        for each key, then are populated by recursively calling processBranch.
-        
-        """
-        nonempty=False
-        if kind is None:
-            item=parent
+            self.source=(os.path.join(os.getcwd(), "contacts.csv"))
         else:
-            item=kind.newItem(None, parent)
-        for key in tree:
-            childData=tree[key]
-            childKind=item.getAttributeAspect(key, "type")
-            value=self.processBranch(item, childData, importRowDict, childKind)
-            if value is not None:
-                item.setAttributeValue(key, value)
-                nonempty=True
-        if nonempty:
-            return item
-        else:
-            if kind is not None:
-                item.delete()
-            return None
-            
-    def createString(self, parent, tree, importRowDict):
-        """Return importRowDict[tree]."""
-        
-        if not importRowDict[tree]:
-            return None
-        else:
-            return importRowDict[tree]
-
-    def createTop(self, parent, tree, importRowDict):
-        """Create the main Kind for this object."""
-        topKind=Globals.repository.find(tree[0])
-        top=topKind.newItem(None, parent)
-        return self.processBranch(top, tree[1], importRowDict)
-
-    def createDate(self, datekey, importRowDict):
-        """Create a RelativeDateTime for importRowDict[datekey].
-        
-        Based on Outlook 2000's export to CSV format for dates.  Dates are of
-        the form "m/d/y", empty dates are expressed as "0/0/00".
-                
-        """
-        
-        dateString=importRowDict[datekey]
-        if dateString in ["0/0/00", ""]:
-            return None
-        else:
-            dateTime= DateTime.Parser.DateTimeFromString(\
-                                          dateString, ('us', 'unknown'))
-            isoString=DateTime.ISO.str(dateTime)
-            return DateTime.Parser.RelativeDateTimeFromString(isoString)
-
-    def createList(self, parent, tree, importRowDict, kind):
-        """Create a list of Items, one for each non-empty element of tree."""
-        returnList = []
-        try:
-            #String and DateTime Kinds don't offer a newItem method
-            item=kind.newItem(None, parent.itsParent)
-        except AttributeError:
-            item=None
-        for branch in tree:
-            value=self.processBranch(item, branch, importRowDict)
-            if value is not None:
-                returnList.append(value)
-                if item is not None:
-                    item=kind.newItem(None, parent.itsParent)
-        if item is not None:
-            #if item was ever set, we'll have an extra item
-            item.delete()
-        if len(returnList) == 0:
-            return None
-        else:
-            return returnList
-
-    def createConcatString(self, keylist, importRowDict):
-        """Concatenate values in importRowDict from keylist's keys."""
-        valueList=[importRowDict[key] for key in keylist]
-        lines=os.linesep.join(valueList)
-        if lines.strip() == "":
-            return None
-        else:
-            return lines
-        
-    def createCondConst(self, const, keylist, importRowDict):
-        """Return const if any items referred to by keylist are nonempty."""
-        if filter(None, [importRowDict[key] for key in keylist]):
-            return const
-        else:
-            return None
-        
-    def processBranch(self, parent, tree, importRowDict, kind=None):
-        """Process a leaf of the translation struct.
-        
-        tree should be a string, a dictionary, or a tuple whose
-        first element is one of the translation constants.  Create a new Item
-        of the appropriate Kind and parent using tree's type to
-        determine the appropriate creation method.  Recurse through the
-        tree.
-        
-        Creation methods should return None if the relevant fields in 
-        importRowDict are empty (empty may differ for different field types and
-        different import formats, for instance Outlook exports empty dates as
-        0/0/00, whereas string formats should return None if they're empty
-        or contain only whitespace.
-        
-        """
-        if type(tree)==dict:
-            return self.createAttributes(parent, tree, importRowDict, kind)
-        elif type(tree) in [str, unicode]:
-            return self.createString(parent, tree, importRowDict)
-        elif type(tree)==tuple:
-            if   tree[0]==TOP:
-                return self.createTop(parent, tree[1:], importRowDict)
-            elif tree[0]==DATETYPE:
-                return self.createDate(tree[1], importRowDict)
-            elif tree[0]==LISTTYPE:
-                return self.createList(parent, tree[1:], importRowDict, kind)
-            elif tree[0]==CONDITIONALCONST:
-                return self.createCondConst(tree[1], tree[2:], importRowDict)
-            elif tree[0]==CONCATTYPE:
-                return self.createConcatString(tree[1:], importRowDict)
-            else:
-                raise Importer.CreationError, \
-                 ("Can't process tree, constant not recognized",\
-                 self.lineNumber)
-        else:
-            raise Importer.CreationError, \
-             ("Can't process tree, type not recognized", self.lineNumber)
-
-    def createObjectFromDict(self, importRowDict):
-        """Create a Contact object and populate it from the given dict."""
-        i=self.processBranch(self.getDestination(),TRANSLATIONMAP,importRowDict)
-        return i
+            self.source=(sourceFile)
+        path=os.path.join(MAPPINGDIR, mapping)
+        reader=MapXML.MapXML(path)
+        self.mapping=reader.streamFile()
 
-    def massageObject(self, object):
+    def postProcess(self, object):
         """Deal with registering homeSection and workSection after the fact."""
         kindPath="//parcels/OSAF/contentmodel/contacts/ContactSection"
         sectionKind=Globals.repository.find(kindPath)



More information about the Commits mailing list