# 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://componentmap.krud.dev/api-documentation/component-map.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
