diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/Jsons.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/Jsons.java index f743570b..2e92b7e1 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/Jsons.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/Jsons.java @@ -1,6 +1,7 @@ package kr.hakdang.cassdio.common.utils; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -21,4 +22,36 @@ public class Jsons { .setSerializationInclusion(JsonInclude.Include.NON_NULL) .registerModules(new ParameterNamesModule(), new Jdk8Module(), new JavaTimeModule()); + public static T toObject(String input, Class toClass) { + try { + return OBJECT_MAPPER.readValue(input, toClass); + } catch (Exception exception) { + throw new IllegalArgumentException(String.format("failed to deserialize [input: (%s) toClass: (%s)]", input, toClass.getSimpleName()), exception); + } + } + + public static T toObject(String input, TypeReference toClass) { + try { + return OBJECT_MAPPER.readValue(input, toClass); + } catch (Exception exception) { + throw new IllegalArgumentException(String.format("failed to deserialize [input: (%s) toClass: (%s)]", input, toClass), exception); + } + } + + public static String toJson(T input) { + try { + return OBJECT_MAPPER.writeValueAsString(input); + } catch (Exception exception) { + throw new IllegalArgumentException(String.format("failed to serialize [input: (%s)]", input), exception); + } + } + + public static String toPrettyJson(T input) { + try { + return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(input); + } catch (Exception exception) { + throw new IllegalArgumentException(String.format("failed to serialize [input: (%s)]", input), exception); + } + } + } diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnection.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnection.java index e3ef3dd1..f07ae143 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnection.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnection.java @@ -25,7 +25,17 @@ public class ClusterConnection { @Builder public ClusterConnection(String contactPoints, int port, String localDatacenter, String username, String password) { - //TODO : Validation + if (StringUtils.isBlank(contactPoints)) { + throw new IllegalArgumentException(String.format("contactPoints(%s) is blank", contactPoints)); + } + + if (port <= 0) { + throw new IllegalArgumentException(String.format("port(%s) can't be less or equal than zero", port)); + } + + if (StringUtils.isBlank(localDatacenter)) { + throw new IllegalArgumentException(String.format("local-datacenter(%s) is blank", localDatacenter)); + } this.contactPoints = contactPoints; this.port = port; diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/info/ClusterInfoRegisterArgs.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/info/ClusterInfoRegisterArgs.java index 5d2809d7..a520cd29 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/info/ClusterInfoRegisterArgs.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/info/ClusterInfoRegisterArgs.java @@ -1,5 +1,6 @@ package kr.hakdang.cassdio.core.domain.cluster.info; +import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -25,6 +26,22 @@ public class ClusterInfoRegisterArgs { @Builder public ClusterInfoRegisterArgs(String clusterName, String contactPoints, int port, String localDatacenter, String username, String password) { + if (StringUtils.isBlank(clusterName)) { + throw new IllegalArgumentException("Cluster name is blank"); + } + + if (StringUtils.isBlank(contactPoints)) { + throw new IllegalArgumentException("Contact points is blank"); + } + + if (port <= 0) { + throw new IllegalArgumentException("Port is less than 0"); + } + + if (StringUtils.isBlank(localDatacenter)) { + throw new IllegalArgumentException("Local datacenter is blank"); + } + this.clusterName = clusterName; this.contactPoints = contactPoints; this.port = port; diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/ClusterKeyspaceDescribeArgs.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/ClusterKeyspaceDescribeArgs.java index 5f38086c..1b5dfac9 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/ClusterKeyspaceDescribeArgs.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/ClusterKeyspaceDescribeArgs.java @@ -1,5 +1,6 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace; +import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -22,6 +23,9 @@ public class ClusterKeyspaceDescribeArgs { @Builder public ClusterKeyspaceDescribeArgs(String keyspace, boolean withChildren, boolean pretty) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspaceName is null or empty"); + } this.keyspace = keyspace; this.withChildren = withChildren; this.pretty = pretty; diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterDescTablesArgs.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterDescTablesArgs.java index b9f31b7d..275db1a5 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterDescTablesArgs.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterDescTablesArgs.java @@ -1,5 +1,6 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; +import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -15,12 +16,20 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class ClusterDescTablesArgs { private String keyspace; - private int pageSize; //TODO : max check + private int pageSize; private String cursor; @Builder public ClusterDescTablesArgs(String keyspace, int pageSize, String cursor) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (pageSize > 100) { + throw new IllegalArgumentException("pageSize can't be greater than 100"); + } + this.keyspace = keyspace; this.pageSize = pageSize; this.cursor = cursor; diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableArgs.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableArgs.java index dd3fd3ff..adfa6c2f 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableArgs.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableArgs.java @@ -1,5 +1,6 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; +import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -25,6 +26,13 @@ public static class ClusterTableGetArgs { @Builder private ClusterTableGetArgs(String keyspace, String table, boolean withTableDescribe) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (StringUtils.isBlank(table)) { + throw new IllegalArgumentException("table can't be null or empty"); + } this.keyspace = keyspace; this.table = table; this.withTableDescribe = withTableDescribe; @@ -43,6 +51,14 @@ public static class ClusterTableListArgs { @Builder private ClusterTableListArgs(String keyspace, int pageSize, String nextPageState) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (pageSize > 100) { + throw new IllegalArgumentException("pageSize can't be greater than 100"); + } + this.keyspace = keyspace; this.pageSize = pageSize; this.nextPageState = nextPageState; @@ -58,12 +74,24 @@ public static class ClusterTablePureSelectArgs { private String keyspace; private String table; - private int pageSize; //TODO : max check + private int pageSize; private String cursor; @Builder public ClusterTablePureSelectArgs(String keyspace, String table, int pageSize, String cursor) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (StringUtils.isBlank(table)) { + throw new IllegalArgumentException("table can't be null or empty"); + } + + if (pageSize > 100) { + throw new IllegalArgumentException("pageSize can't be greater than 100"); + } + this.keyspace = keyspace; this.table = table; this.pageSize = pageSize; diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeArgs.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeArgs.java index a9f458de..a0b761d9 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeArgs.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeArgs.java @@ -1,5 +1,6 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace.udt; +import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -25,6 +26,14 @@ public static class ClusterUDTTypeListArgs { @Builder private ClusterUDTTypeListArgs(String keyspace, int pageSize, String nextPageState) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (pageSize > 100) { + throw new IllegalArgumentException("pageSize can't be greater than 100"); + } + this.keyspace = keyspace; this.pageSize = pageSize; this.nextPageState = nextPageState; @@ -38,12 +47,20 @@ private ClusterUDTTypeListArgs(String keyspace, int pageSize, String nextPageSta public static class ClusterUDTTypeGetArgs { private String keyspace; - private String typeName; + private String type; @Builder public ClusterUDTTypeGetArgs(String keyspace, String type) { + if (StringUtils.isBlank(keyspace)) { + throw new IllegalArgumentException("keyspace can't be null or empty"); + } + + if (StringUtils.isBlank(type)) { + throw new IllegalArgumentException("type can't be null or empty"); + } + this.keyspace = keyspace; - this.typeName = type; + this.type = type; } } diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeGetCommander.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeGetCommander.java index 9176ba9a..fcbd829f 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeGetCommander.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/udt/ClusterUDTTypeGetCommander.java @@ -32,7 +32,7 @@ public ClusterUDTType getType(CqlSession session, ClusterUDTTypeGetArgs args) { .all() .whereColumn(TABLES_KEYSPACE_NAME.getColumnName()).isEqualTo(bindMarker()) .whereColumn(TYPES_TYPE_NAME.getColumnName()).isEqualTo(bindMarker()) - .build(args.getKeyspace(), args.getTypeName()) + .build(args.getKeyspace(), args.getType()) .setPageSize(1); ResultSet rs = session.execute(statement); @@ -41,7 +41,7 @@ public ClusterUDTType getType(CqlSession session, ClusterUDTTypeGetArgs args) { .limit(1) .map(ClusterUDTType::from) .findFirst() - .orElseThrow(() -> new ClusterUDTTypeNotFoundException(String.format("not exists udt type(%s) in keyspace(%s)", args.getTypeName(), args.getKeyspace()))); + .orElseThrow(() -> new ClusterUDTTypeNotFoundException(String.format("not exists udt type(%s) in keyspace(%s)", args.getType(), args.getKeyspace()))); } } diff --git a/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnectionTest.java b/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnectionTest.java new file mode 100644 index 00000000..f3381abc --- /dev/null +++ b/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/ClusterConnectionTest.java @@ -0,0 +1,101 @@ +package kr.hakdang.cassdio.core.domain.cluster; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * ClusterConnectionTest + * + * @author Seungho Kang (will.seungho@webtoonscorp.com) + * @version 1.0.0 + * @since 2024. 07. 07. + */ +class ClusterConnectionTest { + + @Test + void anonymous_cluster_connection() { + // when + ClusterConnection connection = ClusterConnection.builder() + .contactPoints("127.0.0.1") + .port(29042) + .localDatacenter("dc1") + .build(); + + // then + assertThat(connection.isAuthCredentials()).isFalse(); + assertThat(connection.getContactPoints()).isEqualTo("127.0.0.1"); + assertThat(connection.getPort()).isEqualTo(29042); + assertThat(connection.getUsername()).isEqualTo(null); + assertThat(connection.getPassword()).isEqualTo(null); + assertThat(connection.getLocalDatacenter()).isEqualTo("dc1"); + } + + @Test + void authenticated_cluster_connection() { + // when + ClusterConnection connection = ClusterConnection.builder() + .contactPoints("127.0.0.1") + .port(29042) + .localDatacenter("dc1") + .username("will") + .password("will-password") + .build(); + + // then + assertThat(connection.isAuthCredentials()).isTrue(); + assertThat(connection.getContactPoints()).isEqualTo("127.0.0.1"); + assertThat(connection.getPort()).isEqualTo(29042); + assertThat(connection.getUsername()).isEqualTo("will"); + assertThat(connection.getPassword()).isEqualTo("will-password"); + assertThat(connection.getLocalDatacenter()).isEqualTo("dc1"); + } + + + @EmptySource + @ParameterizedTest + void contactPoints_is_required(String contactPoints) { + // when & then + assertThatThrownBy(() -> + ClusterConnection.builder() + .contactPoints(contactPoints) + .port(29042) + .localDatacenter("dc1") + .build() + ).isInstanceOf(IllegalArgumentException.class); + } + + @ValueSource(ints = { + 0, + -1 + }) + @ParameterizedTest + void port_should_be_positive(int port) { + // when & then + assertThatThrownBy(() -> + ClusterConnection.builder() + .contactPoints("127.0.0.1") + .port(port) + .localDatacenter("dc1") + .build() + ).isInstanceOf(IllegalArgumentException.class); + } + + @EmptySource + @ParameterizedTest + void local_datacenter_is_required(String localDatacenter) { + // when & then + assertThatThrownBy(() -> + ClusterConnection.builder() + .contactPoints("127.0.0.1") + .port(9042) + .localDatacenter(localDatacenter) + .build() + ).isInstanceOf(IllegalArgumentException.class); + } + +} diff --git a/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ColumnKindTest.java b/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ColumnKindTest.java new file mode 100644 index 00000000..47bdae35 --- /dev/null +++ b/cassdio-core/src/test/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ColumnKindTest.java @@ -0,0 +1,28 @@ +package kr.hakdang.cassdio.core.domain.cluster.keyspace.table.column; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * ColumnKindTest + * + * @author Seungho Kang (will.seungho@webtoonscorp.com) + * @version 1.0.0 + * @since 2024. 07. 07. + */ +class ColumnKindTest { + + @Test + void find_column_kind() { + assertThat(ColumnKind.findByCode("partition_key")).isEqualTo(ColumnKind.PARTITION_KEY); + assertThat(ColumnKind.findByCode("clustering")).isEqualTo(ColumnKind.CLUSTERING); + assertThat(ColumnKind.findByCode("regular")).isEqualTo(ColumnKind.REGULAR); + } + + @Test + void unknown_column_kind() { + assertThat(ColumnKind.findByCode("blabla")).isEqualTo(ColumnKind.UNKNOWN); + } + +}