CSV Data Source

The concept of Data Sources is used to provide a convenient way to inject data from csv files.

Dependency

<dependency>
    <groupId>de.bmiag.tapir</groupId>
    <artifactId>tapir-datasource-csv</artifactId>
</dependency>

DataSource generation

When using tapir’s immutable data types you can just annotate the type with @CsvDataSource in order to generate a corresponding DataSource.

The generated DataSource assumes that the columns of the csv file correspond to the attribute names of your immutable object.

As csv files are just plain UTF-8 files every value is just a string and you do not have any type information. tapir uses Spring’s ConversionService in order to convert from String to any other type. You can add custom converters by implementing Converter and registering the class as Spring bean (e.g. by annotating it with @Component).

The following csv file can be converted to a list of users just by adding the CsvDataSource annotation.

users.csv

username;password
user1;mysecret
user2;mysafesecret

User.xtend

@Immutable
@CsvDataSource
class User {
  String username
  String password
}

Attribute mapping customization

The column headers do not necessarily match the attribute names. By using @CsvColumn you can map the attribute to any column.

User.xtend

@Immutable
@CsvDataSource
class User {
  @CsvColumn("Name")
  String username
  @CsvColumn("Pass")
  String password
}

More control needed?

@CsvDataSource is just a convenience annotation which triggers a generation process. You could easily implement the DataSource by yourself in order to have more fine-grained control.

It’s recommended to extend AbstractCsvDataSource for csv data sources.

So this is the data source for the User introduced before:

UserCsvDataSource.xtend

@Component
class UserCsvDataSource extends AbstractCsvDataSource<User> {
    def User mapDataSet(CSVRecord csvRecord) {
        User.build[
            username = csvRescord.get("Name")
            password = csvRescord.get("Pass")
        ]
    }
}

Because of the @Component annotation the data source is picked up automatically. whenever you need to convert to other types than String inject and use the ConversionService.