> 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/developer-guides/builder-sdk/transformation-api/obfuscation-api.md).

# Obfuscation API

## API

To extend beyond the available obfuscation implementations the below interface is provided for developers to build and deploy new types.

The key method to be implemented is `obfuscate`.&#x20;

```java
/**
 * Base obfuscationType class type
 */
public interface ObfuscationType<T> extends CustomUserType {
    T obfuscate(Object value) throws ObfuscationException;

    default void validate() throws InvalidSpecificationException{}
}
```

## Reference example

Below is a reference implementation of the `date bucketing` feature.

```java
package com.fractalworks.streams.processors.obfuscation.types;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fractalworks.streams.core.exceptions.InvalidSpecificationException;
import com.fractalworks.streams.processors.obfuscation.ObfuscationException;
import com.fractalworks.streams.processors.obfuscation.ObfuscationType;
import com.google.common.base.Objects;
import org.joda.time.DateTime;

import java.security.SecureRandom;

@JsonRootName(value = "date bucketing")
public class DateVarianceObfuscationType implements ObfuscationType<DateTime> {

    @JsonIgnore
    private final SecureRandom randomGenerator = new SecureRandom();

    private int variance = 120;

    public CustomVarianceObfuscationType() {
        // Required default constructor
    }

    @Override
    public DateTime obfuscate(Object value) throws ObfuscationException {
        if(value instanceof DateTime dateTimeValue){
            int days;
            do {
                days = (randomGenerator.nextInt() % variance);
            } while (days == 0);
            return (randomGenerator.nextBoolean() ? dateTimeValue.plusDays(days).plusMinutes(randomGenerator.nextInt() % variance) : dateTimeValue.minusDays(days).minusMinutes(randomGenerator.nextInt() % variance));
        } else
            throw new ObfuscationException("Passed data type is not supported for this function.");
    }

    public int getVariance() {
        return variance;
    }

    @JsonProperty(value = "variance")
    public void setVariance(int variance) {
        this.variance = variance;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DateVarianceObfuscationType that = (DateVarianceObfuscationType) o;
        return variance == that.variance && Objects.equal(randomGenerator, that.randomGenerator);
    }

    @Override
    public void validate() throws InvalidSpecificationException {
        if( variance <=0){
            throw new InvalidSpecificationException("Invalid variance. Must be greater than zero");
        }
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(randomGenerator, variance);
    }
}
```
