:param source: source data proxy
        :type source: instance of `DataTraversalProxy` or None
        :param target: target data proxy
        :type target: instance of `DataTraversalProxy` or None

def traverse_one(self, attribute, source, target, visitor):
        """
        :param source: source data proxy
        :type source: instance of `DataTraversalProxy` or None
        :param target: target data proxy
        :type target: instance of `DataTraversalProxy` or None
        """
        if __debug__:
            self.__log_traverse_one(self.__trv_path, attribute, source, target)
        prx = source or target
        rel_op = RELATION_OPERATIONS.check(source, target)
        if prx.do_traverse() \
           and (rel_op == prx.relation_operation or attribute is None):
            for attr in prx.get_relationship_attributes():
                # Check cascade settings.
                if not bool(attr.cascade & rel_op):
                    continue
                if not source is None:
                    try:
                        attr_source = source.get_attribute_proxy(attr)
                    except AttributeError:
                        # If the source does not have the attribute set, we
                        # do nothing (as opposed to when the value is None).
                        continue
                else:
                    attr_source = None
                if not target is None:
                    attr_target = target.get_attribute_proxy(attr)
                else:
                    attr_target = None
                attr_rel_op = RELATION_OPERATIONS.check(attr_source,
                                                        attr_target)
                if attr_rel_op == RELATION_OPERATIONS.ADD:
                    if rel_op == RELATION_OPERATIONS.ADD:
                        parent = source
                    else:
                        parent = target
                elif attr_rel_op == RELATION_OPERATIONS.REMOVE:
                    parent = target
                else: # UPDATE
                    parent = target
                card = get_attribute_cardinality(attr)
                if card == CARDINALITY_CONSTANTS.ONE:
                    if attr_source is None and attr_target is None:
                        # If both source and target have None values, there is
                        # nothing to do.
                        continue
                    if attr_rel_op == RELATION_OPERATIONS.ADD:
#                        if not attr_source.get_id() is None:
#                            # We only ADD new items.
#                            continue
                        src_items = [attr_source]
                        tgt_items = None
                    elif attr_rel_op == RELATION_OPERATIONS.REMOVE:
                        src_items = None
                        tgt_items = [attr_target]
                    else: # UPDATE
                        src_items = [attr_source]
                        tgt_items = [attr_target]
                        src_id = attr_source.get_id()
                        tgt_id = attr_target.get_id()
                        if src_id != tgt_id:
                            if not src_id is None:
                                # If the source ID is None, this is a replace
                                # operation (ADD source, REMOVE target).
                                src_target = attr_target.get_matching(src_id)
                                if not src_target is None:
                                    tgt_items.append(src_target)
                else:
                    src_items = attr_source
                    tgt_items = attr_target
                self.__trv_path.push(parent, (source, target), attr, rel_op)
                self.traverse_many(attr, src_items, tgt_items, visitor)
                self.__trv_path.pop() # path.pop()
        visitor.visit(self.__trv_path, attribute, source, target)