> For the complete documentation index, see [llms.txt](https://docs.fractalworks.io/joule/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fractalworks.io/joule/components/connectors/serialisers/serialisation/custom-transform-example.md).

# Custom transform example

## Objective

The objective of this example is to demonstrate how to implement a custom `CustomTransformer` to convert an internal Joule `StreamEvent` object to a domain-specific `Quote` object.

On how to implement a custom transformation, reference the [CustomTransform API documentation](/joule/developer-guides/builder-sdk/connector-api/sinks/customtransformer-api.md).

## Example

```java
public class QuoteTransformer implements CustomTransformer<Quote> {

    public QuoteTransformer() {
        // Required
    }

    @Override
    public Collection<Quote> transform(Collection<StreamEvent> payload) throws TranslationException {
        Collection<Quote> quotes = new ArrayList<>();
        if( payload!= null) {
            for(StreamEvent e : payload){
                quotes.add(transform(e));
            }
        }
        return quotes;
    }

    @Override
    public Quote transform(StreamEvent payload) throws TranslationException {
        return new Quote(
                (String)payload.getValue("symbol"),
                (double)payload.getValue("mid"),
                (double)payload.getValue("bid"),
                (double)payload.getValue("ask"),
                (long)payload.getValue("volume"),
                (double)payload.getValue("volatility"),
                (long)payload.getEventTime(),
                (Date)payload.getValue("date")
                );
    }
}
```

## Explanation

The example demonstrates a custom implementation of the `CustomTransformer` interface, specifically designed to convert a `StreamEvent` objects to domain specific types.

### Constructor

The constructor is required but does not contain any specific logic for this example.

### Transform single event method

This core method that converts the `StreamEvent` object to a single domain specific object. This is performed by a simple attribute mapping from the `StreamEvent` to `Quote` constructor parameter requirements.

```java
@Override
public Quote transform(StreamEvent payload) throws TranslationException {
return new Quote(
        // Mapping
        ... 
        );
}
```

### Transform batch events method

This method is called when in micro-batching mode. It takes a collection of `StreamEvent`s and converts to a collection of domain specific events using the defined single event transform method.

```java
@Override
public Collection<Quote> transform(Collection<StreamEvent> payload) throws TranslationException {
    Collection<Quote> quotes = new ArrayList<>();
    if( payload!= null) {
        for(StreamEvent e : payload){
            quotes.add(transform(e));
        }
    }
    return quotes;
}
```

### Quote attributes description

| Attributes | Description                          | Type        |
| ---------- | ------------------------------------ | ----------- |
| eventTime  | The time the quote was recorded      | Date / time |
| symbol     | The symbol of the asset being quoted | String      |
| bid        | The bid price of the asset           | Double      |
| ask        | The ask price of the asset           | Double      |
| volatility | The volatility of the asset          | Double      |
| volume     | The volume of trades for the asset   | Double      |
| date       | The date the quote was issued        | Date        |
