# UpdaterSettings

## Creating a builder

Settings introduced by BoostedYAML follow builder design pattern, e.g. you may build your own settings using:

```java
UpdaterSettings.builder() /*configure*/ .build()
```

## Basic settings

### Save automatically

```java
Builder#setAutoSave(boolean autoSave)
```

Sets if the file should automatically be saved using [`YamlDocument#save()`](https://dejvokep.gitbook.io/boostedyaml/getting-started/updating-a-file#saving-dumping-a-file) after the updater has finished updating (does not save if nothing's changed).

{% hint style="warning" %}
Not effective if there is no file associated with the document.
{% endhint %}

**Default:** `true` (enabled)

### Document versioning

```java
Builder#setVersioning(@NotNull Versioning versioning)
Builder#setVersioning(@NotNull Pattern pattern, @NotNull String path)
Builder#setVersioning(@NotNull Pattern pattern, @NotNull Path path)
Builder#setVersioning(@NotNull Pattern pattern, @Nullable String documentVersionId, @NotNull String defaultsVersionId)
```

Sets versioning information. You can read more about the document versioning system (DVS) [here](https://dejvokep.gitbook.io/boostedyaml/updater/file-versioning-system).

To supply versioning object carrying DVS information directly, you can use the **first** method. Please always read the method documentation you are going to use.

**Default:** none

### Enable downgrading

```java
Builder#setEnableDowngrading(boolean enableDowngrading)
```

Sets if to enable downgrading.

{% hint style="warning" %}
Effective if and only a [versioning](#file-versioning) is specified.
{% endhint %}

{% hint style="info" %}
**Downgrading is considered to be a situation:**

* when there are **valid** version IDs found for both files (supplied manually or automatically from files),
* the version ID of the user file represents newer version than default file's version ID.

Please note that by specification, the default file has to have a valid ID supplied/specified.
{% endhint %}

If the updater detects downgrading, and it is enabled, the updater will skip relocations, proceeding directly to merging; throws an error otherwise. If configured like so, you may also want to disable [automatic updating](https://dejvokep.gitbook.io/boostedyaml/loadersettings#update-automatically) (if an error is thrown, you won't be able to create the document).

**Default:** `true` (enabled)

### Option sorting

```java
Builder#setOptionSorting(@NotNull OptionSorting optionSorting)
```

Sets how to sort options in sections during merging (last stage of updating).

* `OptionSorting.SORT_BY_DEFAULTS` - Sorts options by their order in the defaults. This setting ensures that entries which will appear in the merged document will be placed into the section **map** in order defined by the defaults.
* `OptionSorting.NONE` - Does not sort (does not introduce any additional memory consumption). This setting ensures that new entries from the defaults will be placed as the last into the section **map**.

{% hint style="success" %}
**The order depends on the map implementation defined by the** [**configured map supplier**](https://dejvokep.gitbook.io/boostedyaml/generalsettings#runtime-defaults)**.**

If the used implementation does not preserve order of the elements (as they were put into the map), avoid additional memory consumption and use `OptionSorting.NONE` instead.
{% endhint %}

**Default:** `OptionSorting.SORT_BY_DEFAULTS`

## Advanced settings

### Merge rules

```java
Builder#setMergeRules(@NotNull Map<MergeRule, Boolean> mergeRules)
Builder#setMergeRule(@NotNull MergeRule rule, boolean preserveUser)
```

Sets merge preservation rules.

Merge rules determine what content to preserve, when there is a block (object) at the same path in both the document that's being updated and defaults. There is no rule for section-section situation - in this case, the updater traverses those sections and compares the **contents**, rather than comparing **them**.

The boolean represents if to preserve content already in the document instead of the equivalent from defaults. Please note that this applies to **blocks** - including their content (comments, also the submappings if a section).

In case of the map-based method, overwrites only rules that are defined in the given [Map](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html).

**Default:** `MergeRule.MAPPINGS` -> `true` (user), `MergeRule.MAPPING_AT_SECTION`-> `false` (default), `MergeRule.SECTION_AT_MAPPING` -> `false` (default)

### Keep all

```java
Builder#setKeepAll(boolean keepAll)
```

Sets if to keep all non-merged (that don't have an equivalent in the defaults) blocks in the document instead of deleting them.

**Default:** `false` (disabled)

### Ignored routes

```java
Builder#addIgnoredRoutes(@NotNull Map<String, Set<Route>> routes)
// +7 methods (including those for string routes)
```

{% hint style="warning" %}
Effective if and only a [versioning](#file-versioning) is specified.
{% endhint %}

Adds routes to ignore if updating to the provided version ID **(see example below)**. Ignored routes and their corresponding blocks and contents will be excluded from merging and will appear in the updated document (no matter the merge rules). Always read the method documentation.

{% hint style="success" %}
**Ignoring routes is generally useful for sections which users can freely extend and their content is not strictly defined.**

In this sense, we can say that you should specify a version ID of the document and routes of such sections (which were in the document with the ID).
{% endhint %}

<details>

<summary>Example</summary>

Let's suppose your document has version ID of 4 and a freely extendable section at route `"a"`, which you'd like to ignore. To achieve this, you can use:

```java
Builder#addIgnoredRoute("4", "a", '.')
```

The section with it's content will now always appear in the updated document.

</details>

**Default:** none

### Relocations

```java
Builder#addRelocation(@NotNull String versionId, @NotNull Route fromRoute, @NotNull Route toRoute)
Builder#addRelocations(@NotNull Map<String, Map<Route, Route>> relocations)
// +6 methods (including those for string routes)
```

{% hint style="warning" %}
Effective if and only a [versioning](#file-versioning) is specified.
{% endhint %}

Adds relocations (in `from route = to route` format) that took effect at the provided version ID.

Relocations represent that some mapping was moved from route *x* to *y*, which implies no content loss while updating. The ID at which a relocation took effect is the ID of the document which included the changes **(see example below)**. Always read the method documentation.

{% hint style="success" %}
**Relocations are useful if you moved something in the document to another place.**
{% endhint %}

<details>

<summary>Example</summary>

Let's say there was a setting at route `"a"` in document which has version ID of 2, but you decided to move it to `"b"` and the document now has ID of 3. You can interpret this using:

```java
Builder#addRelocation("3", "a", "b", '.')
```

</details>

*Updating cycle for each version ID in the corresponding range (first to last): relocations -> mappers -> custom logic.*

**Default:** none

### Mappers

```java
Builder#addMapper(@NotNull String versionId, @NotNull Route route, @NotNull ValueMapper mapper)
Builder#addMappers(@NotNull Map<String, Map<Route, ValueMapper>> mappers)
// +6 methods (including those for string routes)
```

{% hint style="warning" %}
Effective if and only a [versioning](#file-versioning) is specified.
{% endhint %}

Adds mappers to apply to their respective routes, per version ID.

Mappers can be used to map (= transform) a value at a route, to different value or from one type to another (for example from a boolean to an enum, **see example below**). The ID at which to apply a mapper is the ID of the document which included the datatype change. Always read the method documentation.

**Mappers run after relocations, so you can freely combine them.**

{% hint style="success" %}
**Mappers are useful if you decided to change a value to represent the same, but using another datatype (for example, you now have a multi-constant enum for which was previously only true/false setting).**
{% endhint %}

<details>

<summary>Example</summary>

You introduced an enum for a performance setting at route `"c"` inside the document, which was previously represented as true/false:

```java
enum PerformanceMode {
    BEST_PERFORMANCE, BALANCED, BEST_BATTERY_LIFE
}
```

The document is going to be released under version ID of 5 and you'd like to map `false` -> `BEST_BATTERY_LIFE` and true -> `BEST_PERFORMANCE`. You can effectively do this inline using:

```java
Builder#addMapper("5", "c", ValueMapper.section((section, key) ->
    section.getBoolean(key) ? PerformanceMode.BEST_PERFORMANCE : PerformanceMode.BEST_BATTERY_LIFE), '.')
```

</details>

*Updating cycle for each version ID in the corresponding range (first to last): relocations -> mappers -> custom logic.*

**Default:** none

### Custom logic

```java
Builder#addCustomLogic(@NotNull String versionId, @NotNull Consumer<YamlDocument> consumer)
Builder#addCustomLogic(@NotNull Map<String, Map<Route, ValueMapper>> mappers)
// +1 method
```

{% hint style="warning" %}
Effective if and only a [versioning](#file-versioning) is specified.
{% endhint %}

Adds custom logic to run on the document, per version ID.

You can use your own logic to make changes to the document which are not available via the ignored routes, relocations or mappers. The order in which the consumers are run is undefined and may vary.

**Custom logic is run after relocations and mappers, so you can freely combine them.**

*Updating cycle for each version ID in the corresponding range (first to last): relocations -> mappers -> custom logic.*

**Default:** none
