package org.simpleflatmapper.datastax.impl; import com.datastax.driver.core.ColumnMetadata; import com.datastax.driver.core.Session; import com.datastax.driver.core.TableMetadata; import com.datastax.driver.core.querybuilder.*; import org.simpleflatmapper.datastax.BoundStatementMapper; import org.simpleflatmapper.datastax.DatastaxColumnKey; import org.simpleflatmapper.datastax.DatastaxCrud; import org.simpleflatmapper.datastax.DatastaxMapper; import org.simpleflatmapper.datastax.DatastaxMapperBuilder; import org.simpleflatmapper.datastax.DatastaxMapperFactory; import org.simpleflatmapper.datastax.SettableDataMapperBuilder; import java.lang.reflect.Type; import java.util.List; public class DatastaxCrudFactory { public static <T, K> DatastaxCrud<T, K> newInstance( Type target, Type keyTarget, TableMetadata tableMetadata, Session session, DatastaxMapperFactory datastaxMapperFactory) { DatastaxMapperFactory mapperFactory = DatastaxMapperFactory.newInstance(datastaxMapperFactory); return createCrud(target, keyTarget, tableMetadata, session, mapperFactory); } private static <T, K> DatastaxCrud<T, K> createCrud(Type target, Type keyTarget, TableMetadata tableMetadata, Session session, DatastaxMapperFactory mapperFactory) { DatastaxMapper<T> selectMapper = selectMapper(target, tableMetadata, mapperFactory); return new DatastaxCrud<T, K>( session.prepare(insertQuery(tableMetadata)), session.prepare(insertQuery(tableMetadata, "TTL", "TIMESTAMP")), session.prepare(insertQuery(tableMetadata, "TTL" )), session.prepare(insertQuery(tableMetadata, "TIMESTAMP")), session.prepare(readQuery(tableMetadata)), session.prepare(deleteQuery(tableMetadata)), session.prepare(deleteQueryWithTimestamp(tableMetadata)), DatastaxCrudFactory.<T>insertSetter(target, tableMetadata, mapperFactory, 0), DatastaxCrudFactory.<K>keySetter(keyTarget, tableMetadata, mapperFactory, 0), DatastaxCrudFactory.<K>keySetter(keyTarget, tableMetadata, mapperFactory, 1), selectMapper, tableMetadata.getColumns().size(), session); } private static String deleteQuery(TableMetadata tableMetadata) { Delete delete = QueryBuilder.delete().from(tableMetadata); Delete.Where where = delete.where(); List<ColumnMetadata> columns = tableMetadata.getPrimaryKey(); for(ColumnMetadata column : columns) { where.and(QueryBuilder.eq(column.getName(), QueryBuilder.bindMarker())); } return delete.toString(); } private static String deleteQueryWithTimestamp(TableMetadata tableMetadata) { Delete delete = QueryBuilder.delete().from(tableMetadata); delete.using(QueryBuilder.timestamp(QueryBuilder.bindMarker())); Delete.Where where = delete.where(); List<ColumnMetadata> columns = tableMetadata.getPrimaryKey(); for(ColumnMetadata column : columns) { where.and(QueryBuilder.eq(column.getName(), QueryBuilder.bindMarker())); } return delete.toString(); } private static String readQuery(TableMetadata tableMetadata) { Select.Selection select = QueryBuilder.select(); List<ColumnMetadata> columns = tableMetadata.getColumns(); for(ColumnMetadata column : columns) { select.column(column.getName()); } Select.Where where = select.from(tableMetadata).where(); columns = tableMetadata.getPrimaryKey(); for(ColumnMetadata column : columns) { where.and(QueryBuilder.eq(column.getName(), QueryBuilder.bindMarker())); } return where.toString(); } private static String insertQuery(TableMetadata tableMetadata, String... options) { Insert insert = QueryBuilder.insertInto(tableMetadata); if (options != null) { Insert.Options using = insert.using(); for (String option : options) { if ("TTL".equals(option)) { using.and(QueryBuilder.ttl(QueryBuilder.bindMarker())); } else { using.and(QueryBuilder.timestamp(QueryBuilder.bindMarker())); } } } List<ColumnMetadata> columns = tableMetadata.getColumns(); for(ColumnMetadata column : columns) { insert.value(column.getName(), QueryBuilder.bindMarker()); } return insert.toString(); } private static <T> DatastaxMapper<T> selectMapper(Type target, TableMetadata tableMetadata, DatastaxMapperFactory mapperFactory) { DatastaxMapperBuilder<T> mapperBuilder = mapperFactory.newBuilder(target); int i = 0; for(ColumnMetadata columnMetadata : tableMetadata.getColumns()) { mapperBuilder.addMapping(DatastaxColumnKey.of(columnMetadata, i++)); } return mapperBuilder.mapper(); } private static <K> BoundStatementMapper<K> keySetter(Type keyTarget, TableMetadata tableMetadata, DatastaxMapperFactory mapperFactory, int offset) { SettableDataMapperBuilder<K> mapperBuilder = mapperFactory.newBuilderFrom(keyTarget); int i = offset; for(ColumnMetadata columnMetadata : tableMetadata.getPrimaryKey()) { mapperBuilder.addColumn(DatastaxColumnKey.of(columnMetadata, i++)); } return new BoundStatementMapper<K>(mapperBuilder.mapper()); } private static <T> BoundStatementMapper<T> insertSetter(Type target, TableMetadata tableMetadata, DatastaxMapperFactory mapperFactory, int offset) { SettableDataMapperBuilder<T> mapperBuilder = mapperFactory.newBuilderFrom(target); int i = offset; for(ColumnMetadata columnMetadata : tableMetadata.getColumns()) { mapperBuilder.addColumn(DatastaxColumnKey.of(columnMetadata, i++)); } return new BoundStatementMapper<T>(mapperBuilder.mapper()); } }