// Path: src/main/java/com/github/kindrat/cassandra/client/exception/UrlSyntaxException.java
// public class UrlSyntaxException extends ClientException {
//     public UrlSyntaxException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/main/java/com/github/kindrat/cassandra/client/ui/ConnectionData.java
// @Data
// @Builder
// @AllArgsConstructor
// @NoArgsConstructor
// public class ConnectionData {
//     /**
//      * cassandra url containing host and port (localhost:9042)
//      */
//     private String url;
//     /**
//      * cassandra keyspace
//      */
//     private String keyspace;
//     /**
//      * cassandra username
//      */
//     private String username;
//     /**
//      * cassandra password
//      */
//     private String password;
// }
// 
// Path: src/main/java/com/github/kindrat/cassandra/client/ui/DataObject.java
// @ToString
// @EqualsAndHashCode
// @RequiredArgsConstructor
// public class DataObject {
//     @Getter
//     private final int position;
//     private final Map<String, Object> data = new HashMap<>();
// 
//     public void set(String name, Object value) {
//         data.put(name, value);
//     }
// 
//     public Object get(String name) {
//         if ("#".equals(name)) {
//             return position;
//         }
//         return data.get(name);
//     }
// }


import com.datastax.driver.core.*;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
import com.github.kindrat.cassandra.client.exception.UrlSyntaxException;
import com.github.kindrat.cassandra.client.ui.ConnectionData;
import com.github.kindrat.cassandra.client.ui.DataObject;
import javafx.scene.control.TableColumn;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.core.cql.SessionCallback;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import static com.github.nginate.commons.lang.NStrings.format;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.stream.Collectors.toSet;
import static org.springframework.util.ReflectionUtils.findField;
import static org.springframework.util.ReflectionUtils.getField;
            this.template.set(template);
            return template;
        });
    }

    public CompletableFuture<List<String>> getAllKeyspaces(String url, @Nullable String username,
                                                           @Nullable String password) {
        ConnectionData connectionData = new ConnectionData(url, "system_schema", username, password);
        return connect(connectionData)
                .thenApply(template -> template.select("SELECT keyspace_name FROM keyspaces", String.class));
    }

    public CompletableFuture<ResultSet> getAll(String table) {
        return CompletableFuture.supplyAsync(() -> template.get().getCqlOperations()
                .queryForResultSet(format("select * from {}", table)));
    }

    public CompletableFuture<ResultSet> executeStatement(Statement statement) {
        return CompletableFuture.supplyAsync(() -> {
            SessionCallback<ResultSet> callback = session -> session.execute(statement);
            return template.get().getCqlOperations().execute(callback);
        });
    }

    public CompletableFuture<Void> update(TableMetadata metadata, TableColumn.CellEditEvent<DataObject, Object> event) {
        return CompletableFuture.supplyAsync(() -> {
            Stream<ColumnMetadata> primaryKey = metadata.getPrimaryKey().stream();
            Stream<ColumnMetadata> partitionKey = metadata.getPartitionKey().stream();

            Set<String> keyNames = Stream.concat(primaryKey, partitionKey)
// Path: src/main/java/com/github/kindrat/cassandra/client/exception/UrlSyntaxException.java
// public class UrlSyntaxException extends ClientException {
//     public UrlSyntaxException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/main/java/com/github/kindrat/cassandra/client/ui/ConnectionData.java
// @Data
// @Builder
// @AllArgsConstructor
// @NoArgsConstructor
// public class ConnectionData {
//     /**
//      * cassandra url containing host and port (localhost:9042)
//      */
//     private String url;
//     /**
//      * cassandra keyspace
//      */
//     private String keyspace;
//     /**
//      * cassandra username
//      */
//     private String username;
//     /**
//      * cassandra password
//      */
//     private String password;
// }
// 
// Path: src/main/java/com/github/kindrat/cassandra/client/ui/DataObject.java
// @ToString
// @EqualsAndHashCode
// @RequiredArgsConstructor
// public class DataObject {
//     @Getter
//     private final int position;
//     private final Map<String, Object> data = new HashMap<>();
// 
//     public void set(String name, Object value) {
//         data.put(name, value);
//     }
// 
//     public Object get(String name) {
//         if ("#".equals(name)) {
//             return position;
//         }
//         return data.get(name);
//     }
// }


// Path: src/main/java/com/github/kindrat/cassandra/client/service/CassandraClientAdapter.java
import com.datastax.driver.core.*;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
import com.github.kindrat.cassandra.client.exception.UrlSyntaxException;
import com.github.kindrat.cassandra.client.ui.ConnectionData;
import com.github.kindrat.cassandra.client.ui.DataObject;
import javafx.scene.control.TableColumn;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.core.cql.SessionCallback;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import static com.github.nginate.commons.lang.NStrings.format;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.stream.Collectors.toSet;
import static org.springframework.util.ReflectionUtils.findField;
import static org.springframework.util.ReflectionUtils.getField;

            this.template.set(template);
            return template;
        });
    }

    public CompletableFuture<List<String>> getAllKeyspaces(String url, @Nullable String username,
                                                           @Nullable String password) {
        ConnectionData connectionData = new ConnectionData(url, "system_schema", username, password);
        return connect(connectionData)
                .thenApply(template -> template.select("SELECT keyspace_name FROM keyspaces", String.class));
    }

    public CompletableFuture<ResultSet> getAll(String table) {
        return CompletableFuture.supplyAsync(() -> template.get().getCqlOperations()
                .queryForResultSet(format("select * from {}", table)));
    }

    public CompletableFuture<ResultSet> executeStatement(Statement statement) {
        return CompletableFuture.supplyAsync(() -> {
            SessionCallback<ResultSet> callback = session -> session.execute(statement);
            return template.get().getCqlOperations().execute(callback);
        });
    }

    public CompletableFuture<Void> update(TableMetadata metadata, TableColumn.CellEditEvent<DataObject, Object> event) {
        return CompletableFuture.supplyAsync(() -> {
            Stream<ColumnMetadata> primaryKey = metadata.getPrimaryKey().stream();
            Stream<ColumnMetadata> partitionKey = metadata.getPartitionKey().stream();

            Set<String> keyNames = Stream.concat(primaryKey, partitionKey)
                    .map(ColumnMetadata::getName)