# Component Map

The complete API consists of 2 annotations.

## `@ComponentMapKey`

The `@ComponentMapKey` annotation defines the method that returns the keys of the map. The annotated method return type is the type of the map's key.

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

```kotlin
enum class CalculatorOperationType {
    ADD, SUBTRACT, MULTIPLY, DIVIDE
}

internal interface CalculatorOperation {
    @get:ComponentMapKey
    val operationType: CalculatorOperationType

    fun calculate(a: Int, b: Int): Int
}
```

{% endtab %}

{% tab title="Java" %}

```java
public enum CalculatorOperationType {
    ADD, SUBTRACT, MULTIPLY, DIVIDE
}

public interface CalculatorOperation {
    @ComponentMapKey
    CalculatorOperationType getOperationType();

    int calculate(int a, int b);
}
```

{% endtab %}
{% endtabs %}

Lets implement few operations:

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

```kotlin
internal class AddOperation : CalculatorOperation {
    override val type: CalculatorOperationType = CalculatorOperationType.ADD

    override fun calculate(a: Int, b: Int): Int {
        return a + b
    }
}

internal class MultiplyOperation : CalculatorOperation {
    override val type: CalculatorOperationType = CalculatorOperationType.MULTIPLY

    override fun calculate(a: Int, b: Int): Int {
        return a * b
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class AddOperation implements CalculatorOperation {
    @Override
    public CalculatorOperationType getOperationType() {
        return CalculatorOperationType.ADD;
    }

    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
}

public class MultiplyOperation implements CalculatorOperation {
    @Override
    public CalculatorOperationType getOperationType() {
        return CalculatorOperationType.MULTIPLY;
    }

    @Override
    public int calculate(int a, int b) {
        return a * b;
    }
}
```

{% endtab %}
{% endtabs %}

No annotations or any library specific code is required in the implementations.

## @ComponentMap

{% hint style="info" %}
Component Maps can only be injected into properties, other injection methods are not supported.
{% endhint %}

Add the `@ComponentMap` annotation to map to inject.

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

```kotlin
class CalculatorServiceImpl : CalculatorService {
    @ComponentMap
    private lateinit var operations: Map<CalculatorOperationType, CalculatorOperation>

    override fun calculate(type: CalculatorOperationType, a: Int, b: Int): Number {
        val operationHandler = operations[type] ?: throw IllegalArgumentException("Unknown operation type: $type")
        return operationHandler.calculate(a, b)
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class CalculatorServiceImpl implements CalculatorService {
    @ComponentMap
    private Map<CalculatorOperationType, CalculatorOperation> operations;

    @Override
    public int calculate(CalculatorOperationType type, int a, int b) {
        CalculatorOperation operationHandler = operations.get(type);
        if (operationHandler == null) {
            throw new IllegalArgumentException("Unknown operation type: $type");
        }
        return operationHandler.calculate(a, b);
    }
}
```

{% endtab %}
{% endtabs %}

The `@ComponentMap` annotation can also inject list of beans to the map value:

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

```kotlin
@ComponentMap
private lateinit var operations: Map<CalculatorOperationType, List<CalculatorOperation>>
```

{% endtab %}

{% tab title="Java" %}

```java
@ComponentMap
private Map<CalculatorOperationType, List<CalculatorOperation>> operations;
```

{% endtab %}
{% endtabs %}

By defining the value of the map as `List` of beans the library will add all the beans of each key to their relevant list.

For example if you have multiple `AnnouncementSubscriber` for each `AnnouncementType` just change the type of the map value to `List<AnnouncementSubscriber>` and for each `AnnouncementType` the list will contain multiple subscribers.

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

```kotlin
@ComponentMap
    private lateinit var subscribers: Map<AnnouncementType, List<AnnouncementSubscriber>>
```

{% endtab %}

{% tab title="Java" %}

```java
@ComponentMap
private Map<AnnouncementType, List<AnnouncementSubscriber>> subscribers;
```

{% endtab %}
{% endtabs %}
