> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Column calculators

This page provides a description of how we can add a new column calculator. It features an example in which we populate a new field to SaCvaVegaRiskWeight store. The techniques employed are generic examples that can be extended, adapted and repeated for any use case that we need. In all cases, we make minimal changes to the Reference Implementation.

## Step 1 - define datastore field via the customizations config

The first thing we want to do is to add a field that we will populate with our column calculator.

Datastore field additions are made in the `addModifications()` method of `DatastoreCustomisationsConfig` at `cvarc-application/src/main/java/com/activeviam/cvarc/application/cfg/DatastoreCustomisationsConfig.java`. This class lives in your project's `cvarc-application` module and is intended to be edited directly.

[See more customizations achievable with Datastore Helper.](./examples-datastorehelpers)

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@Override
public void addModifications(IDatastoreConfigurator configurator) {
    configurator.appendField("SaCvaVegaRiskWeight", new CustomField("FileName", ILiteralType.STRING));
    configurator.appendField("SaCvaVegaRiskWeight", new CustomField("Math", ILiteralType.DOUBLE));
}
```

## Step 2 - define the column calculator class

Create your column calculator class in `cvarc-application/src/main/java/com/activeviam/cvarc/application/cfg/extensions/`. The calculator must implement `IColumnCalculator<ILineReader>` (from `com.activeviam.source.common.api`). The CRIF as-of-date calculator (`com.activeviam.cvarc.common.source.CrifAsofDateColumnCalculator` in `cvarc-common-lib`) is the canonical reference implementation.

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
package com.activeviam.cvarc.application.cfg.extensions;

import com.activeviam.source.common.api.IColumnCalculator;
import com.activeviam.source.common.api.IColumnCalculationContext;
import com.activeviam.source.csv.api.ILineReader;

public class FileNameColumnCalculator implements IColumnCalculator<ILineReader> {

    private final String columnName;

    public FileNameColumnCalculator(String columnName) {
        this.columnName = columnName;
    }

    @Override
    public String getColumnName() {
        return columnName;
    }

    @Override
    public Object compute(IColumnCalculationContext<ILineReader> context) {
        return context.getContext().getCurrentFile().getName();
    }
}
```

A calculator can also derive its value from other columns on the current row using `context.getValue("columnName")`. The example below populates the `Math` field from `RiskWeight` and `ParameterC`:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
package com.activeviam.cvarc.application.cfg.extensions;

import com.activeviam.source.common.api.IColumnCalculator;
import com.activeviam.source.common.api.IColumnCalculationContext;
import com.activeviam.source.csv.api.ILineReader;

public class MathColumnCalculator implements IColumnCalculator<ILineReader> {

    private final String columnName;

    public MathColumnCalculator(String columnName) {
        this.columnName = columnName;
    }

    @Override
    public String getColumnName() {
        return columnName;
    }

    @Override
    public Object compute(IColumnCalculationContext<ILineReader> context) {
        double riskWeight = (double) context.getValue("RiskWeight");
        double parameterC = (double) context.getValue("ParameterC");
        return riskWeight + parameterC;
    }
}
```

## Step 3 - attach the calculator to a topic

The DLC framework attaches calculators to topics through a topic's `ChannelDescription`. To attach a calculator without re-listing the topic's column set, extend the relevant `*SourceDescription` class, override the topic bean, and use `.toBuilder()` to start from the parent's `CsvTopicDescription` and add the calculator inline.

Example — attaching both calculators to `cvaDeltaTopic`. The same pattern applies to any topic that has an attached channel; chain a `.customField(...)` call per calculator.

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
package com.activeviam.cvarc.application.cfg.extensions;

import com.activeviam.cvarc.starter.cfg.impl.dlc.SASourceDescription;
import com.activeviam.io.dlc.impl.description.topic.CsvTopicDescription;
import com.activeviam.io.dlc.impl.description.topic.channel.ChannelDescription;
import com.activeviam.io.dlc.impl.description.topic.channel.column.calc.AnonymousCustomFieldDescription;
import com.activeviam.io.dlc.impl.utils.NamedEntityResolverService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;

@Configuration
@Primary
public class ExtendedSASourceDescription extends SASourceDescription {

    @Bean
    @Override
    public CsvTopicDescription cvaDeltaTopic(
            NamedEntityResolverService namedEntityResolver,
            Environment env) {
        CsvTopicDescription base = super.cvaDeltaTopic(namedEntityResolver, env);
        return base.toBuilder()
                .channel(ChannelDescription.builder(
                                namedEntityResolver.getTarget(CVA_DELTA_SENSITIVITIES_PUBLISHER))
                        .customField(AnonymousCustomFieldDescription.of(
                                s -> new FileNameColumnCalculator("FileName")))
                        .customField(AnonymousCustomFieldDescription.of(
                                s -> new MathColumnCalculator("Math")))
                        .build())
                .build();
    }
}
```

The `super.cvaDeltaTopic(...)` call inherits the parent's parser and column list; `.toBuilder()` produces a mutable copy you can extend; each `.customField(AnonymousCustomFieldDescription.of(...))` call registers a calculator inline against the channel.

<Note>
  The CRIF example in `SharedSourceDescription.crifBaseTopic(...)` (`cvarc-starter/src/main/java/com/activeviam/cvarc/starter/cfg/impl/dlc/SharedSourceDescription.java`) shows the same library APIs used to register a column calculator from scratch (without `.toBuilder()`).
</Note>

## Step 4 - wire the extension into ApplicationConfig

Add `ExtendedSASourceDescription` to the `@Import` list of `ApplicationConfig` in `cvarc-application/src/main/java/com/activeviam/cvarc/application/cfg/ApplicationConfig.java`. The `@Primary` annotation on the extension class makes Spring prefer your overridden topic bean over the parent's.
