# Annotations

## Basic Mapping

We start by defining two classes, our source class `SimpleEntity` and our destination class `SimpleEntityDisplay`.

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

```kotlin
data class SimpleEntity(
    val name: String,
    val description: String,
    val privateData: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntity {
    private String name;
    private String description;
    private String privateData;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getPrivateData() {
        return privateData;
    }

    public void setPrivateData(String privateData) {
        this.privateData = privateData;
    }
}
```

{% endtab %}
{% endtabs %}

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

```kotlin
data class SimpleEntityDisplay(
    val name: String = "",
    val description: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private String name = "";
    private String description = "";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
```

{% endtab %}
{% endtabs %}

We can now start adding our annotations to the `SimpleEntity` class. In this example, we want to map the `name` and `description` fields to the `name` and `description` fields of the `SimpleEntityDisplay` class, but not the `privateData` field.

To achieve this, we will use the @MappedField annotation on both of these fields. Additionally, we will define `@DefaultMappingTarget` on the `SimpleEntity` class, which will indicate that all fields annotated with `@MappedField` that do not specify a target should be mapped to the `SimpleEntityDisplay` class.

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField
    val name: String,
    @MappedField
    val description: String,
    val privateData: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField
    private String name;
    @MappedField
    private String description;
    private String privateData;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

### Default Mapping Target

`@DefaultMappingTarget` on a class, indicates that all fields annotated with `@MappedField` that do not specify a target should be mapped to this class by default.

## Mapping Target

The mapping target comes into play when you want to map a single source to multiple destinations. The `target` attribute is used to indicate to which class the field should be mapped. If no target is specified the target will be determined by the `@DefaultMappingTarget` on the class.

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField
    @MappedField(target = SimpleEntityExport::class)
    val name: String,
    @MappedField
    val description: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField
    @MappedField(target = SimpleEntityExport.class)
    private String name;
    @MappedField
    private String description;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

In the above code name is mapped once to the `SimpleEntityDisplay` class using the default mapping target, and once to the `SimpleEntityExport` class using the `target` attribute.

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

```kotlin
data class SimpleEntityDisplay(
    val name: String = "",
    val description: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private String name = "";
    private String description = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

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

```kotlin
data class SimpleEntityExport(
    val name: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityExport {
    private String name = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

## Map To Field

By default each `@MappedField` is mapped to a field with the same name in the target class. To change it use the `mapTo` value. For example:

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField(mapTo = "fullName")
    val name: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField(mapTo = "fullName")
    private String name;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

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

```kotlin
data class SimpleEntityDisplay(
    val fullName: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private String fullName = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

## Map From Field

The field name to map the value from.&#x20;

### Field Level

When `mapFrom` is used at the field level, it allows for mapping of nested values.

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

```kotlin
@DefaultMappingTarget(AdvancedEntityDisplay::class)
data class AdvancedEntity(
    // This field will be mapped to the "firstChildName" field in the default target class
    @MappedField(mapFrom = "childName", mapTo = "firstChildName")
    val firstChild: AdvancedChildEntity,

    // This field will be mapped to the "secondChildName" field in the default target class
    @MappedField(mapFrom = "childName", mapTo = "secondChildName")
    val secondChild: AdvancedChildEntity
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(AdvancedEntityDisplay.class)
public class AdvancedEntity {
    // This field will be mapped to the "firstChildName" field in the default target class
    @MappedField(mapFrom = "childName", mapTo = "firstChildName")
    private AdvancedChildEntity firstChild;

    // This field will be mapped to the "secondChildName" field in the default target class
    @MappedField(mapFrom = "childName", mapTo = "secondChildName")
    private AdvancedChildEntity secondChild;
    
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

As you can see above, we use the `mapFrom` attribute to access the `childName` field in `AdvancedChildEntity`.

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

```kotlin
data class AdvancedChildEntity(
    val childName: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class AdvancedChildEntity {
    private String childName;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

And we use the `mapTo` attribute to map the values to the appropriate fields in  `AdvancedEntityDisplay.`

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

```kotlin
data class AdvancedEntityDisplay(
    val firstChildName: String = "",
    val secondChildName: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class AdvancedEntityDisplay {
    private String firstChildName = "";
    private String secondChildName = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

### Type Level

The `@MappedField` annotation can also be used at the type level. When used at the type level, the `mapFrom` attribute is required to indicate the name of the field to use, if left empty an exception will be thrown.

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

```kotlin
@MappedField(target = SimpleEntityDisplay::class, mapFrom = "firstName")
@MappedField(target = SimpleEntityDisplay::class, mapFrom = "lastName")
data class SimpleEntity(
    val firstName: String,
    val lastName: String,
)
```

{% endtab %}

{% tab title="Java" %}

```java
@MappedField(target = SimpleEntityDisplay.class, mapFrom = "firstName")
@MappedField(target = SimpleEntityDisplay.class, mapFrom = "lastName")
public class SimpleEntity {
    private String firstName;
    private String lastName;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

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

```kotlin
data class SimpleEntityDisplay(
    val firstName: String = "",
    val lastName: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private String firstName = "";
    private String lastName = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

## Transformer

Field transformers are a way to transform a field from one type to another when mapping it to a destination class. More about the ins-and-outs of transformers is available here:

{% content-ref url="../features/transformers" %}
[transformers](https://shapeshift.krud.dev/features/transformers)
{% endcontent-ref %}

To configure a transformer for a field use the `transformer` attribute. The `transformer` attribute receives the transformer's class.

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField(transformer = StringToListMappingTransformer::class, mapTo = "stringList")
    val commaDelimitedString: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField(transformer = StringToListMappingTransformer.class, mapTo = "stringList")
    private String commaDelimitedString;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

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

```kotlin
data class SimpleEntityDisplay(
    val stringList: List<String> = emptyList()
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private List<String> stringList = new ArrayList<>();
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Transformers must be registered to the `ShapeShift` instance in order to be used. More info about registering transformers is available in the [transformers page](https://shapeshift.krud.dev/features/transformers#registering-transformers).
{% endhint %}

{% content-ref url="../features/transformers" %}
[transformers](https://shapeshift.krud.dev/features/transformers)
{% endcontent-ref %}

## Auto Mapping

Auto mapping is used to reduce the amount of boiler-place code required to configure mapping between two classes. More info about auto mapping is available here:

{% content-ref url="../features/auto-mapping" %}
[auto-mapping](https://shapeshift.krud.dev/features/auto-mapping)
{% endcontent-ref %}

Auto mapping can be added using the `@AutoMapping` annotation.

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

```kotlin
@AutoMapping(SimpleEntityDisplay::class, strategy = AutoMappingStrategy.BY_NAME)
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    val id: String,
    val name: String,
    val birthDate: Date,
    val email: String,
    val telephone: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@AutoMapping(target = SimpleEntityDisplay.class, strategy = AutoMappingStrategy.BY_NAME)
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    private String id;
    private String name;
    private Date birthDate;
    private String email;
    private String telephone;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

The `@AutoMapping` annotation has two attributes:

1. `target` - If no target is added then the auto mapping will be configured to any target class. It is possible to add multiple `@AutoMapping` annotation for multiple target classes.
2. `strategy` - The [auto mapping strategy](https://shapeshift.krud.dev/features/auto-mapping#auto-mapping-strategy). Default value `NONE`.

## Mapping Condition

Conditions are used to determine wether a field should be mapped according to certain logic. More info about conditions is available here:

{% content-ref url="../features/conditions" %}
[conditions](https://shapeshift.krud.dev/features/conditions)
{% endcontent-ref %}

A condition can be added to annotation mapping using the `condition` attribute.

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField(condition = NotBlankStringCondition::class)
    val name: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField(condition = NotBlankStringCondition.class)
    private String name;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

We mapped the name field and added a condition for the mapping.

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

```kotlin
data class SimpleEntityDisplay(
    val name: String = ""
)
```

{% endtab %}

{% tab title="Java" %}

```java
public class SimpleEntityDisplay {
    private String name = "";
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

The condition receives context with the original value of the field and checks that it is not null or blank.

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

```kotlin
class NotBlankStringCondition : MappingCondition<String> {
    override fun isValid(context: MappingConditionContext<String>): Boolean {
        return !context.originalValue.isNullOrBlank()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class NotBlankStringCondition implements MappingCondition<String> {
    @Override
    public boolean isValid(@NonNull MappingConditionContext<String> context) {
        return context.getOriginalValue() != null && !context.getOriginalValue().trim().isEmpty();
    }
}
```

{% endtab %}
{% endtabs %}

## Override Mapping Strategy

The `overrideMappingStrategy` attribute allows you to override the default mapping strategy configured on the `ShapeShift` instance.&#x20;

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

```kotlin
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
    @MappedField(overrideMappingStrategy = MappingStrategy.MAP_ALL)
    val name: String
)
```

{% endtab %}

{% tab title="Java" %}

```java
@DefaultMappingTarget(SimpleEntityDisplay.class)
public class SimpleEntity {
    @MappedField(overrideMappingStrategy = MappingStrategy.MAP_ALL)
    private String name;
    // Getters and Setters...
}
```

{% endtab %}
{% endtabs %}

More info about mapping strategy is available here:

{% content-ref url="../features/mapping-strategy" %}
[mapping-strategy](https://shapeshift.krud.dev/features/mapping-strategy)
{% endcontent-ref %}
