# Decorators

In some use cases mapping fields is not enough. Sometimes we need to add additional logic to the mapping. For these use cases we have the decorators, the decorators allow us to perform operations on our models after the mapping has finished.

We start with our two classes, our source class `User` and our destination class `UserDisplay`.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
data class User(
    var firstName: String,
    var lastName: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class User {
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
data class UserDisplay(
    var firstName: String,
    var lastName: String,
    var fullName: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class UserDisplay {
    private String firstName;
    private String lastName;
    private String fullName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
}
```

{% endtab %}
{% endtabs %}

In this example, we want to merge the `firstName` and `lastName` fields to the `fullName` field.

## Adding Decorators

Adding decorators is available through the `ShapeShiftBuilder` class. Decorators can be added inline or as a separate class.

### Class Decorators

To create a decorator class implement the `MappingDecorator` interface.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class UserUserDisplayDecorator : MappingDecorator<User, UserDisplay> {
    override fun decorate(context: MappingDecoratorContext<User, UserDisplay>) {
        val (from, to) = context
        to.fullName = "${from.firstName} ${from.lastName}"
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class UserUserDisplayDecorator implements MappingDecorator<User, UserDisplay> {
    @Override
    public void decorate(@NonNull MappingDecoratorContext<User, UserDisplay> mappingDecoratorContext) {
        User from = mappingDecoratorContext.getFrom();
        UserDisplay to = mappingDecoratorContext.getTo();
        to.setFullName(from.getFirstName() + " " + from.getLastName());
    }
}
```

{% endtab %}
{% endtabs %}

And register it to the `ShapeShift` instance.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val shapeShift = ShapeShiftBuilder()
    .withDecorator(UserUserDisplayDecorator())
    .build()
```

{% endtab %}

{% tab title="Java" %}

```java
ShapeShift shapeShift = new ShapeShiftBuilder()
        .withDecorator(User.class, UserDisplay.class, new UserUserDisplayDecorator())
        .build();
```

{% endtab %}
{% endtabs %}

### Inline Decorators

It is also possible to add the decorator logic inline.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val shapeShift = ShapeShiftBuilder()
    .withDecorator(MappingDecorator<User, UserDisplay> {
        val (from, to) = it
        to.fullName = "${from.firstName} ${from.lastName}"
    })
    .build()
```

{% endtab %}

{% tab title="Java" %}

```java
ShapeShift shapeShift = new ShapeShiftBuilder()
        .withDecorator(User.class, UserDisplay.class, mappingDecoratorContext -> {
            User from = mappingDecoratorContext.getFrom();
            UserDisplay to = mappingDecoratorContext.getTo();
            to.setFullName(from.getFirstName() + " " + from.getLastName());
        })
        .build();
```

{% endtab %}
{% endtabs %}
