def copy_frame(frame_id, source_db, target_db):
    # type: (cm.ArbitrationId, cm.CanMatrix, cm.CanMatrix) -> bool
    """
    Copy a Frame identified by ArbitrationId from source CAN matrix to target CAN matrix.
    This function additionally copy all relevant ECUs and Defines.

    :param frame_id: Frame arbitration od
    :param source_db: Source CAN matrix
    :param target_db: Destination CAN matrix
    """
    frame_list = [source_db.frame_by_id(frame_id)]

    for frame in frame_list:
        logger.info("Copying Frame " + frame.name)

        if target_db.frame_by_id(frame.arbitration_id) is not None:
            # frame already in target_db...
            return False

        # copy Frame-Object:
        target_db.add_frame(copy.deepcopy(frame))

        # ECUs:
        # each transmitter of Frame could be ECU that is not listed already
        for transmitter in frame.transmitters:
            target_ecu = target_db.ecu_by_name(transmitter)
            source_ecu = source_db.ecu_by_name(transmitter)
            if source_ecu is not None and target_ecu is None:
                copy_ecu(source_ecu, source_db, target_db)

        # trigger all signals of Frame
        for sig in frame.signals:
            # each receiver of Signal could be ECU that is not listed already
            for receiver in sig.receivers:
                target_ecu = target_db.ecu_by_name(receiver)
                source_ecu = source_db.ecu_by_name(receiver)
                if source_ecu is not None and target_ecu is None:
                    copy_ecu(source_ecu, source_db, target_db)

        # copy all frame-defines
        attributes = frame.attributes
        for attribute in attributes:
            if attribute not in target_db.frame_defines:
                target_db.add_frame_defines(
                    copy.deepcopy(attribute), copy.deepcopy(source_db.frame_defines[attribute].definition))
                target_db.add_define_default(
                    copy.deepcopy(attribute), copy.deepcopy(source_db.frame_defines[attribute].defaultValue))
            # update enum data types if needed:
            if source_db.frame_defines[attribute].type == 'ENUM':
                temp_attr = frame.attribute(attribute, db=source_db)
                if temp_attr not in target_db.frame_defines[attribute].values:
                    target_db.frame_defines[attribute].values.append(copy.deepcopy(temp_attr))
                    target_db.frame_defines[attribute].update()

        # trigger all signals of Frame
        for sig in frame.signals:
            # delete all 'unknown' attributes
            for attribute in sig.attributes:
                target_db.add_signal_defines(
                    copy.deepcopy(attribute), copy.deepcopy(source_db.signal_defines[attribute].definition))
                target_db.add_define_default(
                    copy.deepcopy(attribute), copy.deepcopy(source_db.signal_defines[attribute].defaultValue))
                # update enum data types if needed:
                if source_db.signal_defines[attribute].type == 'ENUM':
                    temp_attr = sig.attribute(attribute, db=source_db)
                    if temp_attr not in target_db.signal_defines[attribute].values:
                        target_db.signal_defines[attribute].values.append(copy.deepcopy(temp_attr))
                        target_db.signal_defines[attribute].update()

    return True
Copy a Frame identified by ArbitrationId from source CAN matrix to target CAN matrix.
    This function additionally copy all relevant ECUs and Defines.

    :param frame_id: Frame arbitration od
    :param source_db: Source CAN matrix
    :param target_db: Destination CAN matrix