From 0cb750d8ca92920915ee655d00e03b155922249d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Tue, 2 Feb 2010 14:30:14 +0000
Subject: [PATCH] - invalid_category_spreadsheet_handler now returns a boolean,
 telling if we should continue processing or not. - Drop "simulation_mode"
 hack and use an invalid_category_spreadsheet_handler accumulating errors
 instead. - Don't fail if some empty sheets are left in the spreadsheet

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@32183 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../Base_getCategoriesSpreadSheetMapping.xml  | 77 ++++++++-----------
 .../CategoryTool_importCategoryFile.xml       | 63 +++++++--------
 product/ERP5/bootstrap/erp5_core/bt/revision  |  2 +-
 3 files changed, 67 insertions(+), 75 deletions(-)

diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_getCategoriesSpreadSheetMapping.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_getCategoriesSpreadSheetMapping.xml
index 2d151090c9..309f77bf76 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_getCategoriesSpreadSheetMapping.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_getCategoriesSpreadSheetMapping.xml
@@ -60,9 +60,13 @@
 `import_file` must be a spreadsheet in a format supported by openoffice\n
 \n
 `invalid_spreadsheet_error_handler` is the callback method that will be called if\n
-the spreadsheet is invalid. The method must recieve as only parameter a string\n
-explaining the error.\n
-If no error_callback is given, the default action is to raise a ValueError.\n
+the spreadsheet is invalid. The method must accept one parameter, an\n
+explanation of the error.\n
+The error handler can return a boolean, true meaning that the rest of the\n
+spreadsheet have to be processed, false meaning that the processing should\n
+stop.\n
+If no error_callback is given, the default action is to raise a ValueError on\n
+the first error encountered.\n
 \n
 The returned mapping has the following structure:\n
   \n
@@ -80,7 +84,6 @@ way that parent always precedes their children.\n
 """\n
 from Products.ERP5Type.Message import translateString\n
 from Products.ERP5OOo.OOoUtils import OOoParser\n
-from Products.ERP5Type.Document import newTempBase\n
 parser = OOoParser()\n
 category_list_spreadsheet_mapping = dict()\n
 error_list = []\n
@@ -91,17 +94,16 @@ def default_invalid_spreadsheet_error_handler(error_message):\n
 if invalid_spreadsheet_error_handler is None:\n
   invalid_spreadsheet_error_handler = default_invalid_spreadsheet_error_handler\n
 \n
-try:\n
-  property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
-except AttributeError:\n
-  # Class tool is too old\n
-  property_id_list = []\n
+# FIXME: we are actually only interested in properties defined on Category\n
+# type information.\n
+property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
 \n
 \n
 def getIDFromString(string=None):\n
   """\n
     This function transform a string to a safe and beautiful ID.\n
     It is used here to create a safe category ID from a string.\n
+    But the code is not really clever...\n
   """\n
   if string is None:\n
     return None\n
@@ -156,8 +158,11 @@ spreadsheet_list = parser.getSpreadsheetsMapping(no_empty_lines=True)\n
 \n
 \n
 for table_name in spreadsheet_list.keys():\n
+  sheet = spreadsheet_list[table_name]\n
+  if not sheet:\n
+    continue\n
   # Get the header of the table\n
-  columns_header = spreadsheet_list[table_name][0]\n
+  columns_header = sheet[0]\n
   # Get the mapping to help us know the property according a cell index\n
   property_map = {}\n
   column_index = 0\n
@@ -204,8 +209,7 @@ for table_name in spreadsheet_list.keys():\n
   # This path_element_list help us to reconstruct the absolute path\n
   path_element_list = []\n
   line_index = 2\n
-  for line in spreadsheet_list[table_name][1:]:\n
-\n
+  for line in sheet[1:]:\n
     # Exclude empty lines\n
     if line.count(\'\') + line.count(None) == len(line):\n
       continue\n
@@ -218,7 +222,6 @@ for table_name in spreadsheet_list.keys():\n
       property_id = property_map[cell_index]\n
       line_data[property_id] = cell\n
       cell_index += 1\n
-\n
     # Analyse every cell of the line\n
     category_property_list = {}\n
     cell_index = 0\n
@@ -277,28 +280,23 @@ for table_name in spreadsheet_list.keys():\n
 \n
           # Detect invalid IDs\n
           if path_element_id in property_id_list:\n
-            if simulation_mode:\n
-              error = newTempBase(context, \'item\')\n
-              error.edit(field_type = \'Invalid ID\', field_category = path_element_id, field_message = translateString("The ID ${id} in ${table} at line ${line}  is invalid, it\'s a reserved property name",mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n
-              error_list.append(error)\n
-            else:\n
-              return invalid_spreadsheet_error_handler(translateString("The ID ${id} in ${table} at line ${line}  is invalid, it\'s a reserved property name",mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n
-\n
-\n
+            cont = invalid_spreadsheet_error_handler(\n
+                      translateString("The ID ${id} in ${table} at line ${line} is invalid, it\'s a reserved property name",\n
+                        mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n
+            if not cont:\n
+              return \n
 \n
           # Detect duplicate IDs\n
           for element in path_element_list[::-1]:\n
             if element[\'depth\'] != element_depth:\n
               break\n
             if element[\'value\'] == path_element_id:\n
-              if simulation_mode:\n
-                error = newTempBase(context, \'item\')\n
-                error.edit(field_type = \'Duplicate ID\', field_category = element[\'value\'], field_message = translateString("Duplicate ID ${id} found in ${table} at line ${line}  ", mapping=dict(id=element[\'value\'], table=table_name, line=line_index)))\n
-                error_list.append(error)\n
-              else:\n
-                return invalid_spreadsheet_error_handler( \n
-                    translateString("Duplicate id found in ${table} at line ${line} : ${id}",\n
+              cont = invalid_spreadsheet_error_handler(\n
+                      translateString(\n
+                      "Duplicate ID found in ${table} at line ${line} : ${id}",\n
                         mapping=dict(id=element[\'value\'], table=table_name, line=line_index)))\n
+              if not cont:\n
+                return\n
 \n
 \n
           # Detect wrong hierarchy\n
@@ -313,17 +311,13 @@ for table_name in spreadsheet_list.keys():\n
                 current_depth = element[\'depth\']\n
                 continue # we are on the direct parent (current level - 1)\n
               else:\n
-                if simulation_mode:\n
-                  error = newTempBase(context, \'item\')\n
-                  error.edit(field_type = \'Wrong hierarchy\', field_category = path_element_id, field_message = translateString("Wrong hierarchy found for ID ${id} and ${depth} in ${table} at line ${line} " ,mapping=dict(id=path_element_id,depth=element_depth, table=table_name, line=line_index)))\n
-                  error_list.append(error)         \n
-                else: \n
-                  return invalid_spreadsheet_error_handler(\n
+                cont = invalid_spreadsheet_error_handler(\n
                         translateString(\n
                            "Wrong hierarchy found for ID ${id} and depth ${depth} in ${table} at line ${line} ",\n
                              mapping=dict(id=path_element_id,\n
                                        depth=element_depth, table=table_name, line=line_index)))\n
-\n
+                if not cont:\n
+                  return\n
 \n
 \n
           # Save the path element\n
@@ -352,7 +346,7 @@ else:\n
         </item>
         <item>
             <key> <string>_params</string> </key>
-            <value> <string>import_file, invalid_spreadsheet_error_handler=None, simulation_mode=False</string> </value>
+            <value> <string>import_file, invalid_spreadsheet_error_handler=None</string> </value>
         </item>
         <item>
             <key> <string>errors</string> </key>
@@ -372,7 +366,7 @@ else:\n
                   <dictionary>
                     <item>
                         <key> <string>co_argcount</string> </key>
-                        <value> <int>3</int> </value>
+                        <value> <int>2</int> </value>
                     </item>
                     <item>
                         <key> <string>co_varnames</string> </key>
@@ -380,13 +374,10 @@ else:\n
                           <tuple>
                             <string>import_file</string>
                             <string>invalid_spreadsheet_error_handler</string>
-                            <string>simulation_mode</string>
                             <string>Products.ERP5Type.Message</string>
                             <string>translateString</string>
                             <string>Products.ERP5OOo.OOoUtils</string>
                             <string>OOoParser</string>
-                            <string>Products.ERP5Type.Document</string>
-                            <string>newTempBase</string>
                             <string>parser</string>
                             <string>dict</string>
                             <string>category_list_spreadsheet_mapping</string>
@@ -396,10 +387,10 @@ else:\n
                             <string>_getattr_</string>
                             <string>context</string>
                             <string>property_id_list</string>
-                            <string>AttributeError</string>
                             <string>getIDFromString</string>
                             <string>content_type</string>
                             <string>hasattr</string>
+                            <string>Products.ERP5Type.Document</string>
                             <string>newTempOOoDocument</string>
                             <string>tmp_ooo</string>
                             <string>_getiter_</string>
@@ -411,6 +402,7 @@ else:\n
                             <string>spreadsheet_list</string>
                             <string>table_name</string>
                             <string>_getitem_</string>
+                            <string>sheet</string>
                             <string>columns_header</string>
                             <string>property_map</string>
                             <string>column_index</string>
@@ -445,7 +437,7 @@ else:\n
                             <string>element</string>
                             <string>path</string>
                             <string>clean_title</string>
-                            <string>error</string>
+                            <string>cont</string>
                             <string>current_depth</string>
                           </tuple>
                         </value>
@@ -460,7 +452,6 @@ else:\n
             <value>
               <tuple>
                 <none/>
-                <int>0</int>
               </tuple>
             </value>
         </item>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/CategoryTool_importCategoryFile.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/CategoryTool_importCategoryFile.xml
index d444b44f2e..b9224fa1c5 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/CategoryTool_importCategoryFile.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/CategoryTool_importCategoryFile.xml
@@ -62,15 +62,8 @@ detailed_report_append = detailed_report_result.append\n
 base_category_id_list = []\n
 category_path_dict = {}\n
 simulation_new_category_id_list = []\n
-try:\n
-  property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
-except AttributeError:\n
-  # Class tool is too old - use an empty list and warn used in detailed report\n
-  property_id_list = []\n
-  if \'warning\' in displayed_report:\n
-    report_line = newTempBase(context, \'item\')\n
-    report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = \'ERP5Type product needs to be upgraded so that portal_classes can supply getPropertySheetPropertyIdList\')    \n
-    detailed_report_append(report_line)\n
+\n
+property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
 \n
 def Object_hasRelation(obj):\n
   # Check if there is some related objets.\n
@@ -80,8 +73,6 @@ def Object_hasRelation(obj):\n
       related_url = related.getRelativeUrl()\n
       if related_url.startswith(obj.getRelativeUrl()):\n
         continue\n
-      elif related_url.startswith(\'portal_simulation\'):\n
-        continue\n
       elif related_url.startswith(\'portal_trash\'):\n
         continue\n
       else:\n
@@ -104,19 +95,29 @@ expired_category_counter = 0\n
 \n
 filename = getattr(import_file, \'filename\', \'?\')\n
 \n
-def invalid_category_spreadsheet_handler(message):\n
-  # action taken when an invalid spreadsheet is provided.\n
-  # we *raise* a Redirect, because we don\'t want the transaction to succeed\n
-  # note, we could make a dialog parameter to allow import invalid spreadsheet:\n
-  raise \'Redirect\', \'%s/view?portal_status_message=%s\' % (\n
-                         context.portal_categories.absolute_url(),\n
-                         message)\n
+# The list of error from simulation mode\n
+error_list = []\n
+if simulation_mode:\n
+  def invalid_category_spreadsheet_handler(message):\n
+    error = newTempBase(context, \'item\')\n
+    error.edit(field_type=\'Error\',\n
+               field_message=message)\n
+    error_list.append(error)\n
+    return True # means continue processing the rest of the document\n
+else:\n
+  def invalid_category_spreadsheet_handler(error_type, path, message):\n
+    # action taken when an invalid spreadsheet is provided.\n
+    # we *raise* a Redirect, because we don\'t want the transaction to succeed\n
+    # note, we could make a dialog parameter to allow import invalid spreadsheet:\n
+    raise \'Redirect\', \'%s/view?portal_status_message=%s\' % (\n
+                           context.portal_categories.absolute_url(),\n
+                           message)\n
 \n
 category_list_spreadsheet_mapping = context.Base_getCategoriesSpreadSheetMapping(import_file,\n
-                                    invalid_spreadsheet_error_handler=invalid_category_spreadsheet_handler, simulation_mode=simulation_mode)\n
+                              invalid_spreadsheet_error_handler=invalid_category_spreadsheet_handler)\n
 \n
-if category_list_spreadsheet_mapping.has_key(\'error_list\'):\n
-  context.REQUEST.other[\'category_import_report\'] = category_list_spreadsheet_mapping[\'error_list\']\n
+if simulation_mode and error_list:\n
+  context.REQUEST.other[\'category_import_report\'] = error_list\n
   return context.CategoryTool_viewImportReport()\n
 \n
 for base_category, category_list in \\\n
@@ -147,7 +148,7 @@ for base_category, category_list in \\\n
               simulation_new_category_id_list.append({\'category\':category_id,\'path\':parent_path})\n
               if \'created\' in displayed_report:\n
                 report_line = newTempBase(context, \'item\')\n
-                report_line.edit(field_type = \'Creation\', field_category = category[\'path\'].split(category_id)[0]+category_id,  field_message = translateString("Will be created new ${type}", mapping=dict(type=category_type)))                \n
+                report_line.edit(field_type = \'Creation\', field_category = category[\'path\'].split(category_id)[0]+category_id,  field_message = translateString("Will be created new ${type}", mapping=dict(type=category_type)))\n
                 detailed_report_append(report_line)\n
             else:\n
               base_path_obj.newContent( portal_type       = category_type\n
@@ -156,7 +157,7 @@ for base_category, category_list in \\\n
                                     )\n
               if \'created\' in displayed_report:\n
                 report_line = newTempBase(context, \'item\')\n
-                report_line.edit(field_type = \'Creation\', field_category = base_path_obj[category_id].getRelativeUrl(), field_message = translateString("Created new ${type}", mapping=dict(type=category_type)))    \n
+                report_line.edit(field_type = \'Creation\', field_category = base_path_obj[category_id].getRelativeUrl(), field_message = translateString("Created new ${type}", mapping=dict(type=category_type)))\n
                 detailed_report_append(report_line)\n
           else:\n
             # The ID is invalid, we must break the loop\n
@@ -164,7 +165,7 @@ for base_category, category_list in \\\n
             is_valid_category = False\n
             if \'warning\' in displayed_report:\n
               report_line = newTempBase(context, \'item\')\n
-              report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = translateString("found invalid ID ${id} ", mapping=dict(id=category_id)))    \n
+              report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = translateString("found invalid ID ${id} ", mapping=dict(id=category_id)))\n
               detailed_report_append(report_line)\n
             break\n
           is_new_category = True\n
@@ -251,23 +252,23 @@ for base_category_id in base_category_id_list:\n
           # TODO: add a dialog parameter allowing to delete this path\n
           if \'warning\' in displayed_report:\n
             report_line = newTempBase(context, \'item\')\n
-            report_line.edit(field_type = \'Warning\', field_category = category.getRelativeUrl(),  field_message = translateString("Category is used and can not be deleted or expired ", mapping=dict()))                \n
+            report_line.edit(field_type = \'Warning\', field_category = category.getRelativeUrl(),  field_message = translateString("Category is used and can not be deleted or expired ", mapping=dict()))\n
             detailed_report_append(report_line)\n
         else:\n
           if existing_category_list == \'keep\' and \'kept\' in displayed_report:\n
             report_line = newTempBase(context, \'item\')\n
-            report_line.edit(field_type = \'Keep\', field_category = category.getRelativeUrl(), field_message = translateString("Kept category", mapping=dict()))                \n
+            report_line.edit(field_type = \'Keep\', field_category = category.getRelativeUrl(), field_message = translateString("Kept category", mapping=dict()))\n
             detailed_report_append(report_line)\n
         kept_category_counter += 1\n
       else:\n
         if existing_category_list == \'delete\' and \'deleted\' in displayed_report:\n
           report_line = newTempBase(context, \'item\')\n
-          report_line.edit(field_type = \'Delete\', field_category = category.getRelativeUrl(), field_message = translateString("Deleted category", mapping=dict()))                \n
+          report_line.edit(field_type = \'Delete\', field_category = category.getRelativeUrl(), field_message = translateString("Deleted category", mapping=dict()))\n
           detailed_report_append(report_line)\n
           deleted_category_counter += 1\n
         if existing_category_list == \'expire\' and \'expired\' in displayed_report:\n
           report_line = newTempBase(context, \'item\')\n
-          report_line.edit(field_type = \'Expire\', field_category = category.getRelativeUrl(), field_message = translateString("Expired category", mapping=dict()))                \n
+          report_line.edit(field_type = \'Expire\', field_category = category.getRelativeUrl(), field_message = translateString("Expired category", mapping=dict()))\n
           detailed_report_append(report_line)\n
           expired_category_counter += 1\n
         category_to_delete_list.append(category.getRelativeUrl())\n
@@ -378,8 +379,6 @@ return context.REQUEST.RESPONSE.redirect(\n
                             <string>simulation_new_category_id_list</string>
                             <string>context</string>
                             <string>property_id_list</string>
-                            <string>AttributeError</string>
-                            <string>report_line</string>
                             <string>Object_hasRelation</string>
                             <string>isValidID</string>
                             <string>new_category_counter</string>
@@ -391,9 +390,9 @@ return context.REQUEST.RESPONSE.redirect(\n
                             <string>expired_category_counter</string>
                             <string>getattr</string>
                             <string>filename</string>
+                            <string>error_list</string>
                             <string>invalid_category_spreadsheet_handler</string>
                             <string>category_list_spreadsheet_mapping</string>
-                            <string>_getitem_</string>
                             <string>_write_</string>
                             <string>_getiter_</string>
                             <string>base_category</string>
@@ -405,6 +404,7 @@ return context.REQUEST.RESPONSE.redirect(\n
                             <string>is_new_category</string>
                             <string>key_list</string>
                             <string>base_path_obj</string>
+                            <string>_getitem_</string>
                             <string>category_id_list</string>
                             <string>parent_path</string>
                             <string>True</string>
@@ -413,6 +413,7 @@ return context.REQUEST.RESPONSE.redirect(\n
                             <string>category_id</string>
                             <string>str</string>
                             <string>category_type</string>
+                            <string>report_line</string>
                             <string>dict</string>
                             <string>None</string>
                             <string>new_category</string>
diff --git a/product/ERP5/bootstrap/erp5_core/bt/revision b/product/ERP5/bootstrap/erp5_core/bt/revision
index 4541cc8666..ce7224cd64 100644
--- a/product/ERP5/bootstrap/erp5_core/bt/revision
+++ b/product/ERP5/bootstrap/erp5_core/bt/revision
@@ -1 +1 @@
-1453
\ No newline at end of file
+1455
\ No newline at end of file
-- 
2.30.9