## InfAdoptedOperation

InfAdoptedOperation — Operation that can be processed by InfAdoptedAlgorithm.

## Stability Level

Unstable, unless otherwise indicated

## Functions

gboolean | inf_adopted_operation_need_concurrency_id ()
InfAdoptedOperation * | inf_adopted_operation_transform ()
InfAdoptedOperation * | inf_adopted_operation_copy ()
InfAdoptedOperationFlags | inf_adopted_operation_get_flags ()
gboolean | inf_adopted_operation_apply ()
InfAdoptedOperation * | inf_adopted_operation_apply_transformed ()
gboolean | inf_adopted_operation_is_reversible ()
InfAdoptedOperation * | inf_adopted_operation_revert ()

## Types and Values

| InfAdoptedOperation
struct | InfAdoptedOperationInterface
enum | InfAdoptedOperationFlags
enum | InfAdoptedConcurrencyId

## Object Hierarchy

        GEnum
        ╰── InfAdoptedConcurrencyId
        GFlags
        ╰── InfAdoptedOperationFlags
        GInterface
        ╰── InfAdoptedOperation

## Prerequisites

InfAdoptedOperation requires GObject.

## Known Implementations

InfAdoptedOperation is implemented by InfAdoptedNoOperation and InfAdoptedSplitOperation.

## Includes

    #include <libinfinity/adopted/inf-adopted-operation.h>

## Description

The InfAdoptedOperation interface must be implemented by operations that are supposed to be used by InfAdoptedAlgorithm. They basically need to define transformation rules for transformation against other operations.

## Functions

### inf_adopted_operation_need_concurrency_id ()

    gboolean
    inf_adopted_operation_need_concurrency_id
                                   (InfAdoptedOperation *operation,
                                    InfAdoptedOperation *against);

This function returns whether transforming `operation` against `against` is not defined unambiguously. In that case, transformation requires a so-called concurrency ID which determines which of the two operations is transformed.

#### Parameters

operation | The InfAdoptedOperation to transform. |
against | The operation to transform against. |

#### Returns

Whether transformation of `operation` against `against` requires a concurrency ID to be defined.

### inf_adopted_operation_transform ()

    InfAdoptedOperation *
    inf_adopted_operation_transform (InfAdoptedOperation *operation,
                                     InfAdoptedOperation *against,
                                     InfAdoptedOperation *operation_lcs,
                                     InfAdoptedOperation *against_lcs,
                                     gint concurrency_id);

Performs an inclusion transformation of `operation` against `against` , meaning that the effect of `against` is included in `operation` .

If `inf_adopted_operation_need_concurrency_id()` returns `TRUE` for `operation` and `against` , then `operation_lcs` and `against_lcs` must not be `NULL`. In this case they must be the same operations as `operation` and `against` at the earlierst state to which both of them can be transformed. This information can then be used to resolve any conflicts in the transformation of `operation` against `against` .

The `concurrency_id` parameter is used if `inf_adopted_operation_need_concurrency_id()` returns `TRUE` and no conflict resolution can be deduced from `operation_lcs` and `against_lcs` . In this case `concurrency_id` defines a unique way to transform the two operations. Usually, this is derived from the user IDs of the users who issued the two conflicting operations.

#### Parameters

operation | The InfAdoptedOperation to transform. |
against | The operation to transform against. |
operation_lcs | The operation at a previous state, or `NULL`. |
against_lcs | The `against` operation at a previous state, or `NULL`. |
concurrency_id | The concurrency ID for the transformation. |

#### Returns

The transformed InfAdoptedOperation, or `NULL` if the transformation failed.

[transfer full][allow-none]

### inf_adopted_operation_copy ()

    InfAdoptedOperation *
    inf_adopted_operation_copy (InfAdoptedOperation *operation);

Returns a copy of `operation` .

#### Parameters

operation | The InfAdoptedOperation to copy. |

#### Returns

A copy of `operation` .

[transfer full]

### inf_adopted_operation_get_flags ()

    InfAdoptedOperationFlags
    inf_adopted_operation_get_flags (InfAdoptedOperation *operation);

Returns the flags for `operation` .

#### Parameters

operation | A InfAdoptedOperation. |

#### Returns

InfAdoptedOperationFlags for `operation` .

### inf_adopted_operation_apply ()

    gboolean
    inf_adopted_operation_apply (InfAdoptedOperation *operation,
                                 InfAdoptedUser *by,
                                 InfBuffer *buffer,
                                 GError **error);

Applies `operation` to `buffer` . The operation is considered to be applied by user `by` . If the operation cannot be applied then `error` is set and the function returns `FALSE`.

#### Parameters

operation | A InfAdoptedOperation. |
by | A InfAdoptedUser. |
buffer | The InfBuffer to apply the operation to. |
error | Location to store error information, if any, or `NULL`. |

#### Returns

`TRUE` on success or `FALSE` on error.

### inf_adopted_operation_apply_transformed ()

    InfAdoptedOperation *
    inf_adopted_operation_apply_transformed
                                   (InfAdoptedOperation *operation,
                                    InfAdoptedOperation *transformed,
                                    InfAdoptedUser *by,
                                    InfBuffer *buffer,
                                    GError **error);

Applies `transformed` to `buffer` . The operation is considered to be applied by user `by` . The operation `transformed` must have originated from `operation` by transformation with `inf_adopted_operation_transform()`.

If `operation` is reversible or does not affect the buffer (see InfAdoptedOperationFlags), this function is equivalent to

`inf_adopted_operation_apply(transformed, by, buffer)`, with

the exception of the return value. In that case the return value will be `operation` itself, with a reference added.

However, if `operation` is not reversible and affects the buffer, the function attempts to construct an operation which is identical to `operation` , but reversible, and returns it. The function can use information from the transformed operation and the buffer to construct the reversible operation. If a reversible operation cannot be constructed, the function returns an additional reference on `operation` , and still applies the transformed operation to the buffer.

For example, an operation that deletes text in a text editor would be transmitting only the position and the length of the text to delete over the network. From that information alone, the operation cannot be made reversible. However, when the operation is applied to the buffer, the actual text that is being removed can be restored by looking it up in the buffer, making the operation reversible.

#### Parameters

operation | A InfAdoptedOperation. |
transformed | A transformed version of `operation` . |
by | The InfAdoptedUser applying the operation. |
buffer | The InfBuffer to apply the operation to. |
error | Location to store error information, if any, or `NULL`. |

#### Returns

A InfAdoptedOperation, or `NULL` on error. Free with `g_object_unref()` when no longer needed.

[transfer full]

### inf_adopted_operation_is_reversible ()

    gboolean
    inf_adopted_operation_is_reversible (InfAdoptedOperation *operation);

Returns whether `operation` is reversible.

#### Parameters

operation | A InfAdoptedOperation. |

#### Returns

Whether `operation` is reversible.

### inf_adopted_operation_revert ()

    InfAdoptedOperation *
    inf_adopted_operation_revert (InfAdoptedOperation *operation);

Returns a new InfAdoptedOperation that undoes the effect of `operation` . If `operation` and then its reverse operation are applied to a buffer (in that order), the buffer remains unchanged.

`operation` must be reversible for this function to be called (i.e. `inf_adopted_operation_is_reversible()` must return TRUE).

#### Parameters

operation | A InfAdoptedOperation. |

#### Returns

The reverse operation of `operation` .

[transfer full]

## Types and Values

### InfAdoptedOperation

    typedef struct _InfAdoptedOperation InfAdoptedOperation;

InfAdoptedOperation is an opaque data type. You should only access it via the public API functions.

### struct InfAdoptedOperationInterface

    struct InfAdoptedOperationInterface {
      gboolean (*need_concurrency_id)(InfAdoptedOperation* operation,
                                      InfAdoptedOperation* against);

      InfAdoptedOperation* (*transform)(InfAdoptedOperation* operation,
                                        InfAdoptedOperation* against,
                                        InfAdoptedOperation* operation_lcs,
                                        InfAdoptedOperation* against_lcs,
                                        InfAdoptedConcurrencyId concurrency_id);

      InfAdoptedOperation* (*copy)(InfAdoptedOperation* operation);

      InfAdoptedOperationFlags (*get_flags)(InfAdoptedOperation* operation);

      gboolean (*apply)(InfAdoptedOperation* operation,
                        InfAdoptedUser* by,
                        InfBuffer* buffer,
                        GError** error);

      InfAdoptedOperation* (*apply_transformed)(InfAdoptedOperation* operation,
                                                InfAdoptedOperation* transformed,
                                                InfAdoptedUser* by,
                                                InfBuffer* buffer,
                                                GError** error);

      InfAdoptedOperation* (*revert)(InfAdoptedOperation* operation);
    };

The virtual methods that need to be implemented by an operation to be used with InfAdoptedAlgorithm.

#### Members

`need_concurrency_id` () | Virtual function to determine whether a concurrency ID is required to transform `operation` against `against` . |

`transform` ()

Virtual function that transform `operation` against `against` and returns a new InfAdoptedOperation as the result of the transformation. `concurrency_id` is either 1 or -1 and can be used to make a decision in case there is no other criteria to decide how to do the transformation, for example when both `operation` and `against` are inserting text at the same position in the buffer.

`copy` () | Virtual function that returns a copy of the operation. |
`get_flags` () | Virtual function that returns the flags of the operation, see InfAdoptedOperationFlags. |
`apply` () | Virtual function that applies the operation to the buffer. `by` is the user that applies the operation. |

`apply_transformed` ()

Virtual function that applies a transformed version of the operation to the buffer. It attempts to use information from the buffer to make the original operation reversible, if it is not already. The implementation of this function is optional, and only needs to be implemented if the operation is not reversible but can be made reversible with additional information from the buffer or the transformed operation.

`revert` () | Virtual function that creates a new operation that undoes the effect of the operation. If `get_flags` does never return the `INF_ADOPTED_OPERATION_REVERSIBLE` flag set, then this is allowed to be `NULL`. |

### enum InfAdoptedOperationFlags

Various flags for InfAdoptedOperation.

#### Members

INF_ADOPTED_OPERATION_AFFECTS_BUFFER | The operation changes the content of the buffer. |
INF_ADOPTED_OPERATION_REVERSIBLE | The operation is reversible, which means that `inf_adopted_operation_revert()` can be called to generate an operation that undoes the effect of the operation. |

### enum InfAdoptedConcurrencyId

A concurrency ID is used to determine which operation to transform in case two similar operations are transformed against each other.

#### Members

INF_ADOPTED_CONCURRENCY_SELF | Transform the operation itself. |
INF_ADOPTED_CONCURRENCY_NONE | Unspecified which operation to transform. |
INF_ADOPTED_CONCURRENCY_OTHER | Transform the other operation. |

## See Also

InfAdoptedRequest, InfAdoptedAlgorithm