parameters: (self, xml=None, object=None, previous_xml=None, force=False, # pylint: disable=redefined-builtin
                   simulate=False, reset=False, xpath_expression=None, **kw)
return_statement: return conflict_list
docstring: A node is updated with some xupdate
        - xml : the xml corresponding to the update, it should be xupdate
        - object : the object on wich we want to apply the xupdate
        - [previous_xml] : the previous xml of the object, it is mandatory
                           when we have sub objects
docstring_summary: A node is updated with some xupdate
        - xml : the xml corresponding to the update, it should be xupdate
        - object : the object on wich we want to apply the xupdate
        - [previous_xml] : the previous xml of the object, it is mandatory
                           when we have sub objects
docstring_tokens: A node is updated with some xupdate - xml : the xml corresponding to the update it should be xupdate - object : the object on wich we want to apply the xupdate - [ previous_xml ] : the previous xml of the object it is mandatory when we have sub objects
function: def updateNode(self, xml=None, object=None, previous_xml=None, force=False, # pylint: disable=redefined-builtin
                   simulate=False, reset=False, xpath_expression=None, **kw):
      """
      A node is updated with some xupdate
        - xml : the xml corresponding to the update, it should be xupdate
        - object : the object on wich we want to apply the xupdate
        - [previous_xml] : the previous xml of the object, it is mandatory
                           when we have sub objects
      """
      conflict_list = []
      if xml is None:
        return []
      xml = self.convertToXml(xml)
      syncml_logger.debug("updateNode with xml %s",
                          etree.tostring(xml, pretty_print=True))
      if xml.tag == '{%s}modifications' % xml.nsmap.get('xupdate'):
        conflict_list += self.applyXupdate(object=object,
                                           xupdate=xml,
                                           previous_xml=previous_xml,
                                           force=force,
                                           simulate=simulate,
                                           reset=reset,
                                           **kw)
      # we may have only the part of an xupdate
      else:
        args = {}
        if self.isProperty(xml):
          keyword = None
          value = xml.get('select')
          if value is not None:
            select_list = value.split('/') # Something like:
                                           #('','object[1]','sid[1]')
            new_select_list = []
            for select_item in select_list:
              if select_item.find('[') >= 0:
                select_item = select_item[:select_item.find('[')]
              new_select_list.append(select_item)
            select_list = new_select_list # Something like : ('','object','sid')
            keyword = select_list[-1] # this will be 'sid'
          data = None
          if xml.xpath('name()') not in XUPDATE_INSERT_OR_ADD_LIST:
            for subnode in xml:
              if subnode.xpath('name()') == XUPDATE_ELEMENT:
                keyword = subnode.get('name')
          else:
            #XXX find something better than hardcoded prefix
            # We can call add node
            conflict_list += self.addNode(xml=xml,
                                          object=object,
                                          force=force,
                                          simulate=simulate,
                                          reset=reset,
                                          **kw)
            return conflict_list
          if xml.xpath('name()') in XUPDATE_DEL:
            conflict_list += self.deleteNode(xml=xml,
                                             object=object,
                                             force=force,
                                             simulate=simulate,
                                             reset=reset,
                                             **kw)
            return conflict_list
          if keyword is None: # This is not a selection, directly the property
            keyword = xml.xpath('name()')
          if keyword not in NOT_EDITABLE_PROPERTY_LIST:
            # We will look for the data to enter
            xpath_expression = xml.get('select', xpath_expression)
            get_target_parent = xml.xpath('name()') in XUPDATE_INSERT_LIST
            context = self.getContextFromXpath(object,
                                             xpath_expression,
                                             get_target_parent=get_target_parent)
            data_type = context.getPropertyType(keyword)
            data = self.convertXmlValue(xml, data_type=data_type)
            args[keyword] = data
            args = self.getFormatedArgs(args=args)
            # This is the place where we should look for conflicts
            # For that we need :
            #   - data : the data from the remote box
            #   - old_data : the data from this box but at the time of the i
            #last synchronization
            #   - current_data : the data actually on this box
            isConflict = False
            if previous_xml and not force:
              previous_xml_tree = self.convertToXml(previous_xml)
              old_result = previous_xml_tree.xpath(xpath_expression)
              if old_result:
                old_data = self.convertXmlValue(old_result[0])
              else:
                raise ValueError('Xpath expression does not apply on previous'\
                                                    ' xml:%r' % xpath_expression)
              current_data = self.getProperty(context, keyword)
              if (old_data != current_data) and (data != current_data) and\
                                              keyword not in FORCE_CONFLICT_LIST:
                # This is a conflict
                isConflict = True
                xml_string = etree.tostring(xml, encoding='utf-8')
                # unattach diff from its parent once copy has been
                # stored on signature
                xml.getparent().remove(xml)
                conflict = kw['signature'].newContent(portal_type='SyncML Conflict',
                                                      origin_value=context,
                                                      property_id=keyword,
                                                      diff_chunk=xml_string)
                if data_type not in DATA_TYPE_LIST:
                  conflict.edit(local_value=current_data,
                                remote_value=data)
                syncml_logger.info("Generated a conflict for %s", keyword)
                conflict_list += [conflict]
            else:
              syncml_logger.info("UpdateNode : no previous xml founds or force")
            # We will now apply the argument with the method edit
            if args and (not isConflict or force) and (not simulate or reset):
              syncml_logger.info("calling updateContent : %s", args)
              self._updateContent(object=context, **args)
              # It is sometimes required to do something after an edit
              if getattr(context, 'manage_afterEdit', None) is not None:
                context.manage_afterEdit()
            else:
              syncml_logger.warning("did not call updateContent on %s", context)
          else:
            syncml_logger.info("UpdateNode : not editable property %s", keyword)
  
          # Specific cases of update
          if keyword == 'object':
            # This is the case where we have to call addNode
            conflict_list += self.addNode(xml=xml,
                                          object=object,
                                          force=force,
                                          simulate=simulate,
                                          reset=reset,
                                          **kw)['conflict_list']
          elif keyword == HISTORY_TAG and not simulate:
            # This is the case where we have to call addNode
            conflict_list += self.addNode(xml=subnode, object=object,
                                          force=force, simulate=simulate,
                                          reset=reset, **kw)['conflict_list']
          elif keyword in (LOCAL_ROLE_TAG, LOCAL_PERMISSION_TAG) and not simulate:
            # This is the case where we have to update Roles or update permission
            #LOG('ERP5Conduit.updateNode', DEBUG, 'we will add a local role')
            #user = self.getSubObjectId(xml)
            #roles = self.convertXmlValue(data,data_type='tokens')
            #object.manage_setLocalRoles(user,roles)
            conflict_list += self.addNode(xml=xml, object=object,
                                         force=force, simulate=simulate,
                                         reset=reset, **kw)['conflict_list']
        else:
          syncml_logger.warning("UpdateNode : not a property %s", etree.tostring(xml, pretty_print=True))
      return conflict_list
function_tokens: def updateNode ( self , xml = None , object = None , previous_xml = None , force = False , # pylint: disable=redefined-builtin simulate = False , reset = False , xpath_expression = None , * * kw ) : conflict_list = [ ] if xml is None : return [ ] xml = self . convertToXml ( xml ) syncml_logger . debug ( "updateNode with xml %s" , etree . tostring ( xml , pretty_print = True ) ) if xml . tag == '{%s}modifications' % xml . nsmap . get ( 'xupdate' ) : conflict_list += self . applyXupdate ( object = object , xupdate = xml , previous_xml = previous_xml , force = force , simulate = simulate , reset = reset , * * kw ) # we may have only the part of an xupdate else : args = { } if self . isProperty ( xml ) : keyword = None value = xml . get ( 'select' ) if value is not None : select_list = value . split ( '/' ) # Something like: #('','object[1]','sid[1]') new_select_list = [ ] for select_item in select_list : if select_item . find ( '[' ) >= 0 : select_item = select_item [ : select_item . find ( '[' ) ] new_select_list . append ( select_item ) select_list = new_select_list # Something like : ('','object','sid') keyword = select_list [ - 1 ] # this will be 'sid' data = None if xml . xpath ( 'name()' ) not in XUPDATE_INSERT_OR_ADD_LIST : for subnode in xml : if subnode . xpath ( 'name()' ) == XUPDATE_ELEMENT : keyword = subnode . get ( 'name' ) else : #XXX find something better than hardcoded prefix # We can call add node conflict_list += self . addNode ( xml = xml , object = object , force = force , simulate = simulate , reset = reset , * * kw ) return conflict_list if xml . xpath ( 'name()' ) in XUPDATE_DEL : conflict_list += self . deleteNode ( xml = xml , object = object , force = force , simulate = simulate , reset = reset , * * kw ) return conflict_list if keyword is None : # This is not a selection, directly the property keyword = xml . xpath ( 'name()' ) if keyword not in NOT_EDITABLE_PROPERTY_LIST : # We will look for the data to enter xpath_expression = xml . get ( 'select' , xpath_expression ) get_target_parent = xml . xpath ( 'name()' ) in XUPDATE_INSERT_LIST context = self . getContextFromXpath ( object , xpath_expression , get_target_parent = get_target_parent ) data_type = context . getPropertyType ( keyword ) data = self . convertXmlValue ( xml , data_type = data_type ) args [ keyword ] = data args = self . getFormatedArgs ( args = args ) # This is the place where we should look for conflicts # For that we need : #   - data : the data from the remote box #   - old_data : the data from this box but at the time of the i #last synchronization #   - current_data : the data actually on this box isConflict = False if previous_xml and not force : previous_xml_tree = self . convertToXml ( previous_xml ) old_result = previous_xml_tree . xpath ( xpath_expression ) if old_result : old_data = self . convertXmlValue ( old_result [ 0 ] ) else : raise ValueError ( 'Xpath expression does not apply on previous' ' xml:%r' % xpath_expression ) current_data = self . getProperty ( context , keyword ) if ( old_data != current_data ) and ( data != current_data ) and keyword not in FORCE_CONFLICT_LIST : # This is a conflict isConflict = True xml_string = etree . tostring ( xml , encoding = 'utf-8' ) # unattach diff from its parent once copy has been # stored on signature xml . getparent ( ) . remove ( xml ) conflict = kw [ 'signature' ] . newContent ( portal_type = 'SyncML Conflict' , origin_value = context , property_id = keyword , diff_chunk = xml_string ) if data_type not in DATA_TYPE_LIST : conflict . edit ( local_value = current_data , remote_value = data ) syncml_logger . info ( "Generated a conflict for %s" , keyword ) conflict_list += [ conflict ] else : syncml_logger . info ( "UpdateNode : no previous xml founds or force" ) # We will now apply the argument with the method edit if args and ( not isConflict or force ) and ( not simulate or reset ) : syncml_logger . info ( "calling updateContent : %s" , args ) self . _updateContent ( object = context , * * args ) # It is sometimes required to do something after an edit if getattr ( context , 'manage_afterEdit' , None ) is not None : context . manage_afterEdit ( ) else : syncml_logger . warning ( "did not call updateContent on %s" , context ) else : syncml_logger . info ( "UpdateNode : not editable property %s" , keyword ) # Specific cases of update if keyword == 'object' : # This is the case where we have to call addNode conflict_list += self . addNode ( xml = xml , object = object , force = force , simulate = simulate , reset = reset , * * kw ) [ 'conflict_list' ] elif keyword == HISTORY_TAG and not simulate : # This is the case where we have to call addNode conflict_list += self . addNode ( xml = subnode , object = object , force = force , simulate = simulate , reset = reset , * * kw ) [ 'conflict_list' ] elif keyword in ( LOCAL_ROLE_TAG , LOCAL_PERMISSION_TAG ) and not simulate : # This is the case where we have to update Roles or update permission #LOG('ERP5Conduit.updateNode', DEBUG, 'we will add a local role') #user = self.getSubObjectId(xml) #roles = self.convertXmlValue(data,data_type='tokens') #object.manage_setLocalRoles(user,roles) conflict_list += self . addNode ( xml = xml , object = object , force = force , simulate = simulate , reset = reset , * * kw ) [ 'conflict_list' ] else : syncml_logger . warning ( "UpdateNode : not a property %s" , etree . tostring ( xml , pretty_print = True ) ) return conflict_list