# Criando o seu próprio Writer and Reader

O real propósito da interface `Value`, como foi dito, é facilitar a comunicação entre o banco de dados e a aplicação. O Diana, por padrão, suporta os tipos comuns existentes na plataforma Java como os tipos primitivos, Wrappers, a nova API de time, etc. Além desses tipos nativamente suportados também é possível criar os seus próprios convetores de maneira transparente. Para isso ele possui duas interfaces:

* `ValueWriter`: Essa interface representa como uma instância de Value será escrita dentro do banco de dados.
* `ValueReader`: Essa interface representa como o valor será lido para ser lido dentro da aplicação Java. Por padrão, o método `<T> T get(Class<T> clazz)` e suas derivações,  T get(TypeSupplier typeSupplier), utilizam essas implementações para realizar essa conversão.

Ambas as interfaces são carregadas a partir do ServiceLoader do Java SE. De modo que, basta seguir exatamente o mesmo princípio já existente no mundo Java. Para facilitar o entendimento, criará um converter para o seguinte tipo.

```java
public class Money { 

    private final String currency; 

    private final BigDecimal value; 

    Money(String currency, BigDecimal value) { 
        this.currency = currency; 
        this.value = value; 
    } 

    public String getCurrency() { 
        return currency; 
    } 

    public BigDecimal getValue() { 
        return value; 
    } 

    @Override 
    public String toString() { 
        return currency + ' ' + value; 
    } 

    public static Money parse(String text) { 
        String[] texts = text.split(" "); 
        return new Money(texts[0], BigDecimal.valueOf(Double.valueOf(texts[1]))); 
    } 
}
```

Com o intuito é criar um simples converter foi utilizado a criação dessa simples representação Monetário. Como se sabe que não é uma boa prática reinventar a roda, em sua aplicação utiliza APIs mais maduras como o [moneta](https://github.com/JavaMoney) que é a implementação de referência da money-api, [JSR 354](https://jcp.org/en/jsr/detail?id=354).

O primeiro passo é a criação da classe que realizará a conversão do tipo para o banco de dados, o `ValueWriter`. Ele possui dois métodos:

* `boolean isCompatible(Class clazz)`: Verifica se a implementação suporta a conversão para esse tipo de classe.
* `S write(T object)`: Uma vez definido que a implementação está apta para realizar a conversão, o próximo passo é realizar a conversão de uma instância `T` para o tipo desejado `S`.

```java
public class MoneyValueWriter implements ValueWriter<Money, String> { 

    @Override 
    public boolean isCompatible(Class clazz) { 
        return Money.class.equals(clazz); 
    } 

    @Override 
    public String write(Money object) { 
        return object.toString(); 
    } 
}
```

Uma vez o valor definido dentro do banco de dados o próximo passo é realizar a leitura dessa informação para a aplicação. Para isso é necessário ter uma especialização do ValueReader. Assim, como o `ValueWriter` ele possui dois métodos:

* `boolean isCompatible(Class clazz)`; Verifica se a implementação está apta para realizar a leitura do tipo desejado.
* `<T> T read(Class<T> clazz, Object value)`; Uma vez compatível, o próximo passo é realizar a operação de leitura para a classe algo T a partir do objeto origem.

```java
public class MoneyValueReader implements ValueReader { 

    @Override 
    public boolean isCompatible(Class clazz) { 
        return Money.class.equals(clazz); 
    } 

    @Override 
    public <T> T read(Class<T> clazz, Object value) { 
        return (T) Money.parse(value.toString()); 
    } 
}
```

Uma vez criado as implementações o próximo passo é cadastrar as implementações de leitura e escrita. Para isso, é necessário criar dois arquivos:

* `META-INF/services/org.jnosql.diana.api.ValueReader`
* `META-INF/services/org.jnosql.diana.api.ValueWriter`

Cada arquivo terá o caminho e a classe da respectiva implementação, Assim:

O arquivo `org.jnosql.diana.api.ValueReader` terá o seguinte conteúdo:

```
my.company.MoneyValueReader
```

O arquivo `org.jnosql.diana.api.ValueWriter` terá o seguinte conteúdo:

```
my.company.MoneyValueWriter
```

```java
        Value value = Value.of("BRL 10.0");
        Money money = value.get(Money.class);
        List<Money> list = value.get(new TypeReference<List<Money>>() {});
        Set<Money> set = value.get(new TypeReference<Set<Money>>() {});;
```


---

# 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://jnosql.gitbook.io/jnosql-book/pt-br/part2/chapter2_1_1.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.
