package ch.alv.components.data.adapter;
import ch.alv.components.core.beans.Identifiable;
import ch.alv.components.core.search.ValuesProvider;
import ch.alv.components.data.DataLayerException;
import ch.alv.components.data.query.NoSuchQueryProviderException;
import ch.alv.components.data.query.QueryFactory;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
/**
* ElasticSearch implementation of the {@link DataStoreAdapter} interface.
*
* @since 1.0.0
*/
public class ElasticsearchDataStoreAdapter<TYPE extends Identifiable<String>> implements DataStoreAdapter<TYPE, String> {
private final ElasticsearchTemplate elasticsearchTemplate;
private final QueryFactory queryFactory;
private final Map<String, Object> factoryServices = new HashMap<>();
public ElasticsearchDataStoreAdapter(ElasticsearchTemplate elasticsearchTemplate, QueryFactory queryFactory) {
this.elasticsearchTemplate = elasticsearchTemplate;
this.queryFactory = queryFactory;
}
@Override
public TYPE save(TYPE entity, Class<TYPE> entityClass) throws DataLayerException {
if (!elasticsearchTemplate.indexExists(entityClass)) {
elasticsearchTemplate.createIndex(entityClass);
elasticsearchTemplate.putMapping(entityClass);
}
IndexQuery indexQuery = new IndexQuery();
if (entity.getId() == null) {
entity.setId(UUID.randomUUID().toString());
}
indexQuery.setId(entity.getId());
indexQuery.setObject(entity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(entityClass, true);
return entity;
}
@Override
public TYPE find(String id, Class<TYPE> entityClass) throws DataLayerException {
GetQuery query = new GetQuery();
query.setId(id);
return elasticsearchTemplate.queryForObject(query, entityClass);
}
@Override
public List<TYPE> find(String queryName, ValuesProvider params, Class<TYPE> entityClass) throws DataLayerException {
try {
SearchQuery query = queryFactory.createQuery(queryName, params, factoryServices, entityClass);
return elasticsearchTemplate.queryForList(query, entityClass);
} catch (NoSuchQueryProviderException e) {
throw new DataLayerException("Could not execute query with name '" + queryName + "'.", e);
}
}
@Override
public List<TYPE> find(Class<TYPE> entityClass) throws DataLayerException {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
return elasticsearchTemplate.queryForList(searchQuery, entityClass);
}
@Override
public void delete(String id, Class<TYPE> entityClass) throws DataLayerException {
elasticsearchTemplate.delete(entityClass, id);
}
}