*/
@BetaPreview
public CollectionFindAndRerankCursor findAndRerank(CollectionFindAndRerankOptions options) {
@@ -1084,28 +1103,85 @@ public CollectionFindAndRerankCursor findAndRerank(CollectionFindAndRerankO
}
/**
- * Finds all documents in the collection.
+ * Finds and reranks documents in the collection that match the given filter using the specified options.
*
* @param filter
- * the query filter
+ * the query filter to apply to the collection
* @param options
- * options of find one
+ * the options used to customize the find and rerank operation
* @return
- * the find iterable interface
+ * a {@link CollectionFindAndRerankCursor} to iterate over the reranked documents
+ *
+ *
*/
@BetaPreview
public CollectionFindAndRerankCursor findAndRerank(Filter filter, CollectionFindAndRerankOptions options) {
return findAndRerank(filter, options, getDocumentClass());
}
+ /**
+ * Finds and reranks documents in the collection that match the given filter using the specified options,
+ * mapping the resulting documents to the specified target type.
+ *
+ * @param filter
+ * the query filter to apply to the collection
+ * @param options
+ * the options used to customize the find and rerank operation
+ * @param newRowType
+ * the target class type to map the results to
+ * @param
+ * the type of the result rows after mapping
+ * @return
+ * a {@link CollectionFindAndRerankCursor} to iterate over the reranked documents mapped to {@code R}
+ *
+ *
+ */
@BetaPreview
public CollectionFindAndRerankCursor findAndRerank(Filter filter, CollectionFindAndRerankOptions options, Class newRowType) {
return new CollectionFindAndRerankCursor<>(this, filter, options, newRowType);
}
+ /**
+ * Finds and reranks documents in the collection using the given filter and options,
+ * and returns a paginated result containing reranked items mapped to the specified result type.
+ *
+ * @param filter
+ * the query filter to apply to the collection
+ * @param options
+ * the options used to customize the find and rerank operation
+ * @param newRowType
+ * the target class type to map the results to
+ * @param
+ * the type of the result items after mapping
+ * @return
+ * a {@link Page} of {@link RerankedResult} objects containing the paginated reranked results
+ *
+ *
+ */
@BetaPreview
- public Page> findAndRerankPage(Filter filter, CollectionFindAndRerankOptions options, Class newRowType) {
+ public Page> findAndRerankPage(Filter filter, CollectionFindAndRerankOptions options, Class newRowType) {
Command findAndRerankCommand = Command
.create("findAndRerank")
.withFilter(filter);
@@ -1132,7 +1208,7 @@ public Page> findAndRerankPage(Filter filter, CollectionFind
sortVector = apiResponse.getStatus().getSortVector();
}
- List> results = new ArrayList<>();
+ List> results = new ArrayList<>();
List documents = apiResponse.getData().getDocuments();
List documentResponses = apiResponse.getStatus().getDocumentResponses();
if (documents == null || documentResponses == null) {
@@ -1157,7 +1233,7 @@ public Page> findAndRerankPage(Filter filter, CollectionFind
Document documentResponse = documentResponses.get(i);
Map scores = documentResponse.getMap("scores", String.class, Double.class);
- results.add(new RerankResult<>(results1, scores));
+ results.add(new RerankedResult<>(results1, scores));
}
// PageState is always NULL
return new Page<>(null, results, sortVector);
@@ -1181,6 +1257,8 @@ public Page> findAndRerankPage(Filter filter, CollectionFind
* This list, along with the maximum page size and the next page state, is used to construct the {@link Page} object returned by the method.
*
*
+ * @param type of the result rows after mapping
+ * @param newRowType The class type to which the documents should be mapped.
* @param filter The filter criteria used to select documents from the collection.
* @param options The {@link CollectionFindOptions} providing additional query parameters, such as sorting and pagination.
* @return A {@link Page} object containing the documents that match the query, along with pagination information.
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindAndRerankCursor.java b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindAndRerankCursor.java
index 7c3318fa..4cacb473 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindAndRerankCursor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindAndRerankCursor.java
@@ -26,11 +26,13 @@
import com.datastax.astra.client.core.query.Filter;
import com.datastax.astra.client.core.query.Projection;
import com.datastax.astra.client.core.query.Sort;
-import com.datastax.astra.client.core.rerank.RerankResult;
+import com.datastax.astra.client.core.rerank.RerankedResult;
+import com.datastax.astra.client.core.vector.DataAPIVector;
import com.datastax.astra.internal.command.AbstractCursor;
import lombok.Getter;
import java.util.ArrayList;
+import java.util.Optional;
/**
@@ -50,7 +52,7 @@
* @param
* working object for results, should be same as DOC if no projections
*/
-public class CollectionFindAndRerankCursor extends AbstractCursor> {
+public class CollectionFindAndRerankCursor extends AbstractCursor> {
/**
* Input table reference
@@ -68,8 +70,11 @@ public class CollectionFindAndRerankCursor extends AbstractCursor newRowType;
/**
@@ -81,10 +86,12 @@ public class CollectionFindAndRerankCursor extends AbstractCursor dataSource, Filter filter, CollectionFindAndRerankOptions options, Class recordType) {
- super((Class>) (Class>) RerankResult.class);
+ super((Class>) (Class>) RerankedResult.class);
this.dataSource = dataSource;
this.filter = filter;
this.options = options;
@@ -136,7 +143,8 @@ public CollectionFindAndRerankCursor filter(Filter newFilter) {
/**
* Creates a new {@link CollectionFindAndRerankCursor} with an updated projection.
*
- * @param newProjection the new projection to apply
+ * @param newProjection
+ * the new projection to apply
* @return a new {@link CollectionFindAndRerankCursor} instance with the specified projection
*/
public CollectionFindAndRerankCursor project(Projection... newProjection) {
@@ -149,7 +157,8 @@ public CollectionFindAndRerankCursor project(Projection... newProjection)
/**
* Creates a new {@link CollectionFindAndRerankCursor} with a specified sort order.
*
- * @param sort the sort criteria to apply
+ * @param sort
+ * the sort criteria to apply
* @return a new {@link CollectionFindAndRerankCursor} instance with the specified sort order
*/
public CollectionFindAndRerankCursor sort(Sort... sort) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindCursor.java b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindCursor.java
index 788cf11f..cee96530 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindCursor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/cursor/CollectionFindCursor.java
@@ -27,6 +27,7 @@
import com.datastax.astra.client.core.query.Filter;
import com.datastax.astra.client.core.query.Projection;
import com.datastax.astra.client.core.query.Sort;
+import com.datastax.astra.client.core.vector.DataAPIVector;
import com.datastax.astra.client.tables.definition.rows.Row;
import com.datastax.astra.internal.command.AbstractCursor;
import com.datastax.astra.internal.serdes.tables.RowMapper;
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/options/CollectionFindAndRerankOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/options/CollectionFindAndRerankOptions.java
index 0344cdf3..2364cb2f 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/options/CollectionFindAndRerankOptions.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/collections/commands/options/CollectionFindAndRerankOptions.java
@@ -113,6 +113,12 @@ public CollectionFindAndRerankOptions sort(Sort... sorts) {
return this;
}
+ /**
+ * Return the sort clause as an arryr
+ *
+ * @return
+ * Sort clause
+ */
public Sort[] getSortArray() {
return this.sort;
}
@@ -189,9 +195,14 @@ public CollectionFindAndRerankOptions rerankOn(String rerankOn) {
return this;
}
-
- public CollectionFindAndRerankOptions rerankQuery(String $lexical) {
- this.rerankQuery = rerankOn;
+ /**
+ * Add a rerankQuery clause in the find block
+ *
+ * @param rerankQuery value for rerankQuery options
+ * @return current command
+ */
+ public CollectionFindAndRerankOptions rerankQuery(String rerankQuery) {
+ this.rerankQuery = rerankQuery;
return this;
}
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/CollectionDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/CollectionDefinition.java
index 03bee5c2..219a1f48 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/CollectionDefinition.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/CollectionDefinition.java
@@ -346,6 +346,12 @@ public LexicalOptions getLexical() {
return lexical;
}
+ /**
+ * Builder pattern, disabled lexical
+ *
+ * @return
+ * self reference
+ */
public CollectionDefinition disableLexical() {
if (getLexical() == null) {
lexical(new LexicalOptions().enabled(false));
@@ -427,20 +433,27 @@ public CollectionDefinition rerank(CollectionRerankOptions collectionRerankOptio
/**
* Builder pattern.
*
- * @param reranker
- * reranker
+ * @param provider
+ * reranker provider
+ * @param model
+ * model
* @return self reference
*/
- public CollectionDefinition rerank(String reranker) {
+ public CollectionDefinition rerank(String provider, String model) {
if (getRerank() == null) {
rerank = new CollectionRerankOptions().enabled(true);
}
getRerank()
.enabled(true)
- .service(new RerankServiceOptions().provider(reranker));
+ .service(new RerankServiceOptions().provider(provider).modelName(model));
return this;
}
+ /**
+ * Builder pattern, disable reranking
+ *
+ * @return self reference
+ */
public CollectionDefinition disableRerank() {
if (getRerank() == null) {
rerank = new CollectionRerankOptions().enabled(false);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/documents/Document.java b/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/documents/Document.java
index 524599a7..bc1fc927 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/documents/Document.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/collections/definition/documents/Document.java
@@ -42,6 +42,7 @@
import com.datastax.astra.client.core.vector.DataAPIVector;
import com.datastax.astra.client.core.vectorize.Vectorize;
import com.datastax.astra.client.exceptions.InvalidFieldExpressionException;
+import com.datastax.astra.client.exceptions.UnexpectedDataAPIResponseException;
import com.datastax.astra.internal.serdes.DataAPISerializer;
import com.datastax.astra.internal.serdes.collections.DocumentSerializer;
import com.datastax.astra.internal.utils.Assert;
@@ -358,7 +359,7 @@ public Document id(T id) {
* self reference
*/
public Document vectorize(String passage) {
- return appendIfNotNull(DataAPIKeywords.VECTORIZE.getKeyword(), Vectorize.of(passage));
+ return appendIfNotNull(DataAPIKeywords.VECTORIZE.getKeyword(), new Vectorize(passage));
}
/**
@@ -385,7 +386,7 @@ public Document vectorize(Vectorize vectorize) {
*/
@BetaPreview
public Document vectorize(String passage, String setPassage) {
- return appendIfNotNull(DataAPIKeywords.VECTORIZE.getKeyword(), Vectorize.of(passage, setPassage));
+ return appendIfNotNull(DataAPIKeywords.VECTORIZE.getKeyword(), new Vectorize(passage, setPassage));
}
/**
@@ -444,10 +445,31 @@ public Optional getVectorize() {
* vector list
*/
@JsonIgnore
+ @SuppressWarnings("unchecked")
public Optional getVector() {
- return Optional
- .ofNullable((float[]) documentMap.get(DataAPIKeywords.VECTOR.getKeyword()))
- .map(DataAPIVector::new);
+ if (!documentMap.containsKey(DataAPIKeywords.VECTOR.getKeyword())) {
+ return Optional.empty();
+ }
+
+ Object o = documentMap.get(DataAPIKeywords.VECTOR.getKeyword());
+
+ // Get a vector from a list of doubles
+ if (o instanceof DataAPIVector) {
+ return Optional.of((DataAPIVector) o);
+ } else if (o instanceof ArrayList> list && !list.isEmpty() && list.get(0) instanceof Double) {
+ ArrayList a = (ArrayList) list;
+ float[] floatArray = new float[a.size()];
+ for (int i = 0; i < a.size(); i++) {
+ floatArray[i] = a.get(i).floatValue();
+ }
+ return Optional.of(new DataAPIVector(floatArray));
+ } else if (o instanceof float[] array) {
+ // Get a vector from a float array
+ return Optional.of(new DataAPIVector(array));
+ } else {
+ throw new UnexpectedDataAPIResponseException("Could not parse $vector of type " + o.getClass().getName() +
+ " to a DataAPIVector. Expected a list of Double, a float array or binary data");
+ }
}
/**
@@ -712,6 +734,21 @@ public List getList(@NonNull final String key, @NonNull final Class cl
return constructValuesList(key, clazz, null);
}
+ /**
+ * Gets the list value of the given key, casting the list elements to the given {@code Class}. This is useful to avoid having
+ * casts in client code, though the effect is the same.
+ *
+ * @param
+ * type of the key
+ * @param
+ * type of the value
+ * @param key the key
+ * @param keyClass the non-null class to cast the list value to
+ * @param valueClass the type of the value class
+ * @return the list value of the given key, or null if the instance does not contain this key.
+ * @throws ClassCastException if the elements in the list value of the given key is not of type T or the value is not a list
+ * @since 3.10
+ */
public Map getMap(@NonNull final String key, @NonNull final Class keyClass, @NonNull final Class valueClass) {
return constructValuesMap(key, keyClass, valueClass, null);
}
@@ -823,6 +860,9 @@ public String toJson() {
* Check if the given dot-delimited path exists as a key (final segment).
* e.g. containsKey("foo.bar") returns true if "bar" is present in the Map
* located at "foo".
+ *
+ * @param key for key
+ * @return if the key is present
*/
public boolean containsKey(String key) {
Assert.hasLength(key, "Field name should not be null");
@@ -838,6 +878,14 @@ public boolean containsKey(String key) {
return true;
}
+ /**
+ * Check if the given dot-delimited path exists as a key (final segment).
+ * e.g. containsKey("foo.bar") returns true if "bar" is present in the Map
+ * located at "foo".
+ *
+ * @param fieldPathSegment for key
+ * @return if the key is present
+ */
public Object get(final String[] fieldPathSegment) {
return get(EscapeUtils.escapeFieldNames(fieldPathSegment));
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/hybrid/HybridLimits.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/hybrid/HybridLimits.java
index 3a4cc063..da96b51d 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/hybrid/HybridLimits.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/hybrid/HybridLimits.java
@@ -26,21 +26,50 @@
import java.util.HashMap;
import java.util.Map;
+/**
+ * Represents the limits for lexical and vector data.
+ */
@Data
public class HybridLimits {
+ /**
+ * The limit for the hybrid data when vectorize and lexical are used.
+ */
Integer limit;
+ /**
+ * The limit for the lexical data.
+ */
Map mapOfLimits;
+ /**
+ * Constructor.
+ *
+ * @param limit
+ * the limit for the hybrid data.
+ */
public HybridLimits(Integer limit) {
this.limit = limit;
}
+ /**
+ * Constructor.
+ *
+ * @param mapOfLimits
+ * the map of limits for the hybrid data.
+ */
public HybridLimits(Map mapOfLimits) {
this.mapOfLimits = mapOfLimits;
}
+ /**
+ * Add a limit for the lexical data.
+ *
+ * @param limit
+ * lexical limit.
+ * @return
+ * self reference
+ */
public HybridLimits lexical(Integer limit) {
if (mapOfLimits == null) {
mapOfLimits = new HashMap<>();
@@ -49,6 +78,14 @@ public HybridLimits lexical(Integer limit) {
return this;
}
+ /**
+ * Add a limit for the vector data.
+ *
+ * @param limit
+ * vector limit.
+ * @return
+ * self reference
+ */
public HybridLimits vector(Integer limit) {
if (mapOfLimits == null) {
mapOfLimits = new HashMap<>();
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Analyzer.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Analyzer.java
index fe9d2952..864829db 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Analyzer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Analyzer.java
@@ -23,43 +23,108 @@
import com.datastax.astra.internal.serdes.core.AnalyzerSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
+import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
+/**
+ * Analyzer used for indexing and searching 'lexical' data.
+ */
@Data
@JsonSerialize(using = AnalyzerSerializer.class)
public class Analyzer {
- /** In the case of String analyzer */
+ /** Analyzer definition as a string like 'standard' */
String strAnalyzer;
- /** In the case of Document analyzer, free structure */
+ /**
+ * Represents the tokenizer used by the analyzer.
+ */
LexicalFilter tokenizer;
+ /** Represents the filters for a text analyzer */
List filters;
+ /** Represents the char filters for a text analyzer */
List charFilters;
+ /**
+ * Default constructor.
+ */
public Analyzer() {
}
+ /**
+ * Constructor with analyzer definition.
+ *
+ * @param strAnalyzer
+ * the analyzer definition
+ */
public Analyzer(String strAnalyzer) {
this.strAnalyzer = strAnalyzer;
}
+ /**
+ * Constructor with analyzer type.
+ *
+ * @param strAnalyzer
+ * the analyzer type
+ */
+ public Analyzer(AnalyzerTypes strAnalyzer) {
+ this(strAnalyzer.getValue());
+ }
+
+ /**
+ * Define a tokenizer by its name.
+ *
+ * @param name
+ * the analyzer name
+ * @return
+ * current reference
+ */
public Analyzer tokenizer(String name) {
return tokenizer(name, null);
}
+
+ /**
+ * Define a tokenizer by its name and arguments.
+ *
+ * @param name
+ * the analyzer name
+ * @param args
+ * the arguments for the analyzer
+ * @return
+ * current reference
+ */
public Analyzer tokenizer(String name, Map args) {
this.tokenizer = new LexicalFilter().name(name).args(args);;
return this;
}
+ /**
+ * Adds a filter to the analyzer.
+ *
+ * @param name
+ * the name of the filter
+ * @return
+ * current reference
+ */
public Analyzer addFilter(String name) {
return addFilter(name, null);
}
+
+ /**
+ * Adds a filter to the analyzer.
+ *
+ * @param name
+ * the name of the filter
+ * @param args
+ * the arguments for the filter
+ * @return
+ * current reference
+ */
public Analyzer addFilter(String name, Map args) {
if (filters == null) {
filters = new java.util.ArrayList<>();
@@ -68,9 +133,28 @@ public Analyzer addFilter(String name, Map args) {
return this;
}
+ /**
+ * Adds a char filter to the analyzer.
+ *
+ * @param name
+ * the name of the filter
+ * @return
+ * current reference
+ */
public Analyzer addChartFilter(String name) {
return addChartFilter(name, null);
}
+
+ /**
+ * Adds a char filter to the analyzer.
+ *
+ * @param name
+ * the name of the filter
+ * @param args
+ * the arguments for the filter
+ * @return
+ * current reference
+ */
public Analyzer addChartFilter(String name, Map args) {
if (charFilters == null) {
charFilters = new java.util.ArrayList<>();
@@ -79,44 +163,67 @@ public Analyzer addChartFilter(String name, Map args) {
return this;
}
- public Analyzer(AnalyzerTypes strAnalyzer) {
- this.strAnalyzer = strAnalyzer.getValue();
- }
-
- @NoArgsConstructor
+ /**
+ * Definition of filters and tokenizers
+ */
+ @Getter
public static class LexicalFilter {
+ /** Name of the filter */
String name;
+ /** Arguments for the filter */
Map args;
+ /**
+ * Default constructor.
+ */
+ public LexicalFilter() {
+ }
+
+ /**
+ * Sets the name of the filter.
+ *
+ * @param name
+ * the name of the filter
+ * @return
+ * current reference
+ */
public LexicalFilter name(String name) {
this.name = name;
return this;
}
+ /**
+ * Sets the arguments for the filter.
+ *
+ * @param args
+ * the arguments for the filter
+ * @return
+ * current reference
+ */
public LexicalFilter args(Map args) {
this.args = args;
return this;
}
- public LexicalFilter arg(String key, String value) {
+ /**
+ * Adds an argument to the filter.
+ *
+ * @param key
+ * the key of the argument
+ * @param value
+ * the value of the argument
+ * @return
+ * current reference
+ */
+ public LexicalFilter addArg(String key, String value) {
if (args == null) {
args = new java.util.HashMap<>();
}
args.put(key, value);
return this;
}
-
- public String getName() {
- return name;
- }
-
- public Map getArgs() {
- return args;
- }
}
-
-
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/AnalyzerTypes.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/AnalyzerTypes.java
index dcf9f71e..ba842ed2 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/AnalyzerTypes.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/AnalyzerTypes.java
@@ -22,6 +22,10 @@
import lombok.Getter;
+/**
+ * Enum representing different types of analyzers.
+ * Each enum constant corresponds to a specific analyzer type.
+ */
@Getter
public enum AnalyzerTypes {
@@ -31,20 +35,53 @@ public enum AnalyzerTypes {
*/
STANDARD("standard"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
LETTER("letter"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
LOWERCASE("lowercase"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
WHITESPACE("whitespace"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
N_GRAM("n-gram"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
EDGE_N_GRAM("edge_n-gram"),
+ /**
+ * Filters StandardTokenizer output that divides text
+ * into terms on word boundaries and then uses the LowerCaseFilter.
+ */
KEYWORD("keyword");
+ /**
+ * The string value of the analyzer type.
+ */
final String value;
+ /**
+ * Constructor for the enum.
+ *
+ * @param value
+ * string value
+ */
AnalyzerTypes(String value) {
this.value = value;
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Lexical.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Lexical.java
index 73c74aa1..ee3486d8 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Lexical.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/Lexical.java
@@ -26,12 +26,24 @@
import lombok.Data;
import lombok.NonNull;
+/**
+ * Lexical data.
+ */
@Data
@JsonSerialize(using = LexicalSerializer.class)
public class Lexical {
+ /**
+ * Lexical data.
+ */
private String text;
+ /**
+ * Default constructor.
+ *
+ * @param text
+ * lexical data
+ */
public Lexical(@NonNull String text) {
this.text = text;
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/LexicalFilters.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/LexicalFilters.java
index beec069d..413ecc2a 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/LexicalFilters.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/lexical/LexicalFilters.java
@@ -20,9 +20,11 @@
* #L%
*/
-import com.datastax.astra.client.core.vector.SimilarityMetric;
import lombok.Getter;
+/**
+ * Lexical filters used for indexing and searching 'lexical' data.
+ */
@Getter
public enum LexicalFilters {
@@ -32,33 +34,34 @@ public enum LexicalFilters {
*/
LOWERCASE("lowercase"),
+ /**
+ * Filter with stop words
+ */
STOP("stop"),
+ /**
+ * Filter with synonyms
+ */
SYNONYM("synonym"),
+ /**
+ * Filter with synonyms and graph
+ */
SYNONYM_GRAPH("synonym_graph");
+ /**
+ * The value of the filter.
+ */
final String value;
- LexicalFilters(String value) {
- this.value = value;
- }
-
/**
- * Build from the key.
+ * Constructor.
*
* @param value
- * string value
- * @return
- * enum value
+ * the value of the filter.
*/
- public static LexicalFilters fromValue(String value) {
- for (LexicalFilters filter : LexicalFilters.values()) {
- if (filter.getValue().equalsIgnoreCase(value)) {
- return filter;
- }
- }
- throw new IllegalArgumentException("Unknown LexicalFilters: " + value);
+ LexicalFilters(String value) {
+ this.value = value;
}
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/options/BaseOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/options/BaseOptions.java
index ac826751..9402ed08 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/options/BaseOptions.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/options/BaseOptions.java
@@ -23,6 +23,7 @@
import com.datastax.astra.client.core.headers.EmbeddingAPIKeyHeaderProvider;
import com.datastax.astra.client.core.headers.EmbeddingHeadersProvider;
import com.datastax.astra.client.core.commands.CommandType;
+import com.datastax.astra.client.core.headers.RerankingAPIKeyHeaderProvider;
import com.datastax.astra.client.core.headers.RerankingHeadersProvider;
import com.datastax.astra.client.core.http.HttpClientOptions;
import com.datastax.astra.internal.command.CommandObserver;
@@ -165,6 +166,14 @@ public T embeddingAuthProvider(EmbeddingHeadersProvider embeddingAuthProvider) {
return (T) this;
}
+ /**
+ * Provide the reranking service API key.
+ *
+ * @param rerankingHeadersProvider
+ * authentication provider
+ * @return
+ * service key
+ */
public T rerankingAuthProvider(RerankingHeadersProvider rerankingHeadersProvider) {
Assert.notNull(rerankingHeadersProvider, "rerankHeadersProvider");
getDataAPIClientOptions().rerankingHeadersProvider(rerankingHeadersProvider);
@@ -184,6 +193,19 @@ public T embeddingApiKey(String apiKey) {
return embeddingAuthProvider(new EmbeddingAPIKeyHeaderProvider(apiKey));
}
+ /**
+ * Provide the reranking service API key.
+ *
+ * @param apiKey
+ * target api key
+ * @return
+ * service key
+ */
+ public T rerankingApiKey(String apiKey) {
+ Assert.hasLength(apiKey, "apiKey");
+ return rerankingAuthProvider(new RerankingAPIKeyHeaderProvider(apiKey));
+ }
+
/**
* Provide the token.
*
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/query/Sort.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/query/Sort.java
index 258d949c..d5f36568 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/query/Sort.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/query/Sort.java
@@ -236,4 +236,19 @@ public static Sort hybrid(Hybrid hybrid) {
.build();
}
+ /**
+ * Build a sort clause with vectorize.
+ *
+ * @param hybrid
+ * hybrid sort
+ * @return
+ * sort instance.
+ */
+ public static Sort hybrid(String hybrid) {
+ return internalBuilder()
+ .field(DataAPIKeywords.HYBRID.getKeyword())
+ .hybrid(new Hybrid(hybrid))
+ .build();
+ }
+
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankProviderTypes.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankProviderTypes.java
index d105df81..6242f789 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankProviderTypes.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankProviderTypes.java
@@ -22,19 +22,33 @@
import lombok.Getter;
+/**
+ * Rerank provider types.
+ */
@Getter
public enum RerankProviderTypes {
/**
- * Filters StandardTokenizer output that divides text
- * into terms on word boundaries and then uses the LowerCaseFilter.
+ * Cohere reranker
*/
COHERE("cohere"),
+ /**
+ * bm25 reranker
+ */
BM25("bm25");
+ /**
+ * Rerank provider type.
+ */
final String value;
+ /**
+ * Constructor.
+ *
+ * @param value
+ * string value
+ */
RerankProviderTypes(String value) {
this.value = value;
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankServiceOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankServiceOptions.java
index de8ae6a8..13c8c276 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankServiceOptions.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankServiceOptions.java
@@ -28,6 +28,9 @@
import java.util.HashMap;
import java.util.Map;
+/**
+ * Options for the Rerank service at collection/table creation.
+ */
@Data
@Getter @Setter
public class RerankServiceOptions {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankResult.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankedResult.java
similarity index 68%
rename from astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankResult.java
rename to astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankedResult.java
index a241d064..9f63b9a9 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankResult.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/rerank/RerankedResult.java
@@ -24,14 +24,34 @@
import java.util.Map;
+/**
+ * Wrapper for the rerank result.
+ *
+ * @param
+ * document result type
+ */
@Getter
-public class RerankResult {
+public class RerankedResult {
+ /**
+ * Document result.
+ */
private final DOC document;
+ /**
+ * Score map.
+ */
private final Map scores;
- public RerankResult(DOC document, Map scores) {
+ /**
+ * Constructor.
+ *
+ * @param document
+ * document result
+ * @param scores
+ * score map
+ */
+ public RerankedResult(DOC document, Map scores) {
this.document = document;
this.scores = scores;
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/vector/DataAPIVector.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/vector/DataAPIVector.java
index 19d8717c..cf8dc536 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/vector/DataAPIVector.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/vector/DataAPIVector.java
@@ -24,6 +24,7 @@
import lombok.Getter;
import java.io.Serializable;
+import java.util.ArrayList;
/**
* DataAPIVector is a vector of embeddings.
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/core/vectorize/Vectorize.java b/astra-db-java/src/main/java/com/datastax/astra/client/core/vectorize/Vectorize.java
index 1015bfeb..47a829f0 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/core/vectorize/Vectorize.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/core/vectorize/Vectorize.java
@@ -32,25 +32,36 @@
@JsonSerialize(using = VectorizeSerializer.class)
public class Vectorize {
+ /**
+ * The passage to vectorize
+ */
final String passage;
+ /**
+ * The passage to set
+ */
final String setPassage;
+ /**
+ * Default constructor.
+ *
+ * @param passage
+ * the passage to vectorize
+ */
public Vectorize(String passage) {
this(passage, null);
}
+ /**
+ * Constructor with passage and setPassage
+ *
+ * @param passage
+ * the passage to vectorize
+ * @param setPassage
+ * the passage to set
+ */
public Vectorize(@NonNull String passage, String setPassage) {
this.passage = passage;
this.setPassage = setPassage;
}
-
- public static Vectorize of(String passage) {
- return new Vectorize(passage);
- }
-
- public static Vectorize of(String passage, String setPassage) {
- return new Vectorize(passage, setPassage);
- }
-
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/CreateKeyspaceOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/CreateKeyspaceOptions.java
new file mode 100644
index 00000000..2b78b536
--- /dev/null
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/CreateKeyspaceOptions.java
@@ -0,0 +1,77 @@
+package com.datastax.astra.client.databases.commands.options;
+
+/*-
+ * #%L
+ * Data API Java Client
+ * --
+ * Copyright (C) 2024 DataStax
+ * --
+ * Licensed under the Apache License, Version 2.0
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import com.datastax.astra.client.admin.AdminOptions;
+import com.datastax.astra.client.core.commands.CommandType;
+import com.datastax.astra.client.core.options.BaseOptions;
+import com.datastax.astra.client.core.options.DataAPIClientOptions;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import static com.datastax.astra.client.tables.Table.DEFAULT_TABLE_SERIALIZER;
+
+/**
+ * Set of options used when creating a table
+ */
+@Setter
+@Accessors(fluent = true, chain = true)
+public class CreateKeyspaceOptions extends BaseOptions {
+
+ /** Improve syntax. */
+ public static final CreateKeyspaceOptions IF_NOT_EXISTS = new CreateKeyspaceOptions().ifNotExists(true);
+
+ /**
+ * Condition to upsert the table.
+ */
+ boolean ifNotExists = true;
+
+ /**
+ * Change the keyspace in the database.
+ */
+ boolean updateDBKeyspace = false;
+
+ /**
+ * Default constructor
+ */
+ public CreateKeyspaceOptions() {
+ super(null, CommandType.DATABASE_ADMIN, AdminOptions.DEFAULT_SERIALIZER, null);
+ }
+
+ /**
+ * Gets ifNotExists
+ *
+ * @return value of ifNotExists
+ */
+ public boolean isIfNotExists() {
+ return ifNotExists;
+ }
+
+ /**
+ * Gets updateDBKeyspace
+ *
+ * @return value of updateDBKeyspace
+ */
+ public boolean isUpdateDBKeyspace() {
+ return updateDBKeyspace;
+ }
+}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/DropKeyspaceOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/DropKeyspaceOptions.java
new file mode 100644
index 00000000..d93fe2b2
--- /dev/null
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/commands/options/DropKeyspaceOptions.java
@@ -0,0 +1,63 @@
+package com.datastax.astra.client.databases.commands.options;
+
+/*-
+ * #%L
+ * Data API Java Client
+ * --
+ * Copyright (C) 2024 DataStax
+ * --
+ * Licensed under the Apache License, Version 2.0
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import com.datastax.astra.client.admin.AdminOptions;
+import com.datastax.astra.client.core.commands.CommandType;
+import com.datastax.astra.client.core.options.BaseOptions;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import static com.datastax.astra.client.tables.Table.DEFAULT_TABLE_SERIALIZER;
+
+/**
+ * Set of options used when creating a table
+ */
+@Setter
+@Accessors(fluent = true, chain = true)
+public class DropKeyspaceOptions extends BaseOptions {
+
+ /** Improve syntax. */
+ public static final DropKeyspaceOptions IF_EXISTS = new DropKeyspaceOptions().ifExists(true);
+
+ /**
+ * Condition to upsert the table.
+ */
+ boolean ifExists = true;
+
+ /**
+ * Default constructor
+ */
+ public DropKeyspaceOptions() {
+ super(null, CommandType.DATABASE_ADMIN, AdminOptions.DEFAULT_SERIALIZER, null);
+ }
+
+ /**
+ * Accessor for serialization.
+ *
+ * @return
+ * accessor for serialization
+ */
+ public boolean isIfExists() {
+ return ifExists;
+ }
+
+}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceDefinition.java
new file mode 100644
index 00000000..ea992ed4
--- /dev/null
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceDefinition.java
@@ -0,0 +1,100 @@
+package com.datastax.astra.client.databases.definition.keyspaces;
+
+/*-
+ * #%L
+ * Data API Java Client
+ * --
+ * Copyright (C) 2024 - 2025 DataStax
+ * --
+ * Licensed under the Apache License, Version 2.0
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import com.datastax.astra.client.core.options.DataAPIClientOptions;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Keyspace definition.
+ */
+@Data
+public class KeyspaceDefinition {
+
+ /**
+ * The name of the keyspace.
+ */
+ private String name = DataAPIClientOptions.DEFAULT_KEYSPACE;
+
+ /**
+ * The replication of the namespace.
+ */
+ private Map replication;
+
+ /**
+ * Default constructor
+ */
+ public KeyspaceDefinition() {
+ }
+
+ /**
+ * Name for the keyspace.
+ *
+ * @param name
+ * keyspace name
+ * @return
+ * instance of the options populated
+ *
+ */
+ public KeyspaceDefinition name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Enforce the creation of a namespace with SimpleStrategy.
+ *
+ * @param replicationFactor
+ * replication factor
+ * @return
+ * instance of the options populated
+ *
+ */
+ public KeyspaceDefinition simpleStrategy(int replicationFactor) {
+ if (replication == null) {
+ replication = new HashMap<>();
+ }
+ replication.put("class", KeyspaceReplicationStrategy.SIMPLE_STRATEGY.getValue());
+ replication.put("replication_factor", replicationFactor);
+ return this;
+ }
+
+ /**
+ * Enforce the creation of a namespace with NetworkTopology strategy.
+ *
+ * @param datacenters
+ * list of datacenters with replication factors
+ * @return
+ * instance of the options populated
+ */
+ public KeyspaceDefinition networkTopologyStrategy(Map datacenters) {
+ if (replication == null) {
+ replication = new HashMap<>();
+ }
+ replication.put("class", KeyspaceReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY.getValue());
+ replication.putAll(datacenters);
+ return this;
+ }
+
+}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceInformation.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceInformation.java
index ec10addc..6d8d5dd5 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceInformation.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceInformation.java
@@ -58,39 +58,6 @@ public KeyspaceInformation(String name) {
this.name = name;
}
- /**
- * Replication strategies
- */
- @Getter
- public enum ReplicationStrategy {
-
- /**
- * The simple strategy, for development environments.
- */
- SIMPLE_STRATEGY("SimpleStrategy"),
-
- /**
- * The network topology strategy, for production environments.
- */
- NETWORK_TOPOLOGY_STRATEGY("NetworkTopologyStrategy");
-
- /**
- * Enum value
- */
-
- private final String value;
-
- /**
- * Constructor.
- *
- * @param value
- * value for the replication
- */
- ReplicationStrategy(String value) {
- this.value = value;
- }
- }
-
/** {@inheritDoc} */
@Override
public String toString() {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceOptions.java
index e8ebd1bf..5313a4ad 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceOptions.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceOptions.java
@@ -21,28 +21,27 @@
*/
import lombok.Getter;
+import lombok.Setter;
import java.util.HashMap;
import java.util.Map;
-import static com.datastax.astra.client.databases.definition.keyspaces.KeyspaceInformation.ReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY;
-import static com.datastax.astra.client.databases.definition.keyspaces.KeyspaceInformation.ReplicationStrategy.SIMPLE_STRATEGY;
-
/**
* Options to create a Namespace.
*/
@Getter
+@Setter
public class KeyspaceOptions {
/**
* The replication of the namespace.
*/
- private final Map replication;
+ private Map replication;
/**
* Default Constructor.
*/
- private KeyspaceOptions() {
+ public KeyspaceOptions() {
replication = new HashMap<>();
}
@@ -57,7 +56,7 @@ private KeyspaceOptions() {
*/
public static KeyspaceOptions simpleStrategy(int replicationFactor) {
KeyspaceOptions options = new KeyspaceOptions();
- options.replication.put("class", SIMPLE_STRATEGY.getValue());
+ options.replication.put("class", KeyspaceReplicationStrategy.SIMPLE_STRATEGY.getValue());
options.replication.put("replication_factor", replicationFactor);
return options;
}
@@ -72,9 +71,11 @@ public static KeyspaceOptions simpleStrategy(int replicationFactor) {
*/
public static KeyspaceOptions networkTopologyStrategy(Map datacenters) {
KeyspaceOptions options = new KeyspaceOptions();
- options.replication.put("class", NETWORK_TOPOLOGY_STRATEGY.getValue());
+ options.replication.put("class", KeyspaceReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY.getValue());
options.replication.putAll(datacenters);
return options;
}
+
+
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceReplicationStrategy.java b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceReplicationStrategy.java
new file mode 100644
index 00000000..60cc27b9
--- /dev/null
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/databases/definition/keyspaces/KeyspaceReplicationStrategy.java
@@ -0,0 +1,55 @@
+package com.datastax.astra.client.databases.definition.keyspaces;
+
+/*-
+ * #%L
+ * Data API Java Client
+ * --
+ * Copyright (C) 2024 - 2025 DataStax
+ * --
+ * Licensed under the Apache License, Version 2.0
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import lombok.Getter;
+
+/**
+ * Available Keyspace replication strategy.
+ */
+@Getter
+public enum KeyspaceReplicationStrategy {
+
+ /**
+ * The simple strategy, for development environments.
+ */
+ SIMPLE_STRATEGY("SimpleStrategy"),
+
+ /**
+ * The network topology strategy, for production environments.
+ */
+ NETWORK_TOPOLOGY_STRATEGY("NetworkTopologyStrategy");
+
+ /**
+ * Enum value
+ */
+ private final String value;
+
+ /**
+ * Constructor.
+ *
+ * @param value
+ * value for the replication
+ */
+ KeyspaceReplicationStrategy(String value) {
+ this.value = value;
+ }
+}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/DataAPIHttpException.java b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/DataAPIHttpException.java
index 66d6ef55..bf2e3c48 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/DataAPIHttpException.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/DataAPIHttpException.java
@@ -44,6 +44,8 @@ public DataAPIHttpException(String errorMessage) {
*
* @param errorMessage
* error message
+ * @param code
+ * error code
*/
public DataAPIHttpException(String code, String errorMessage) {
super(code, errorMessage);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/ErrorCodesServer.java b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/ErrorCodesServer.java
index 85bfe0b1..0ff5ee37 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/ErrorCodesServer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/ErrorCodesServer.java
@@ -22,6 +22,9 @@
import lombok.Getter;
+/**
+ * Error codes for server-side errors.
+ */
@Getter
public enum ErrorCodesServer {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/InvalidFieldExpressionException.java b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/InvalidFieldExpressionException.java
index 88c4dcf2..9ce1da5d 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/InvalidFieldExpressionException.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/InvalidFieldExpressionException.java
@@ -43,6 +43,8 @@ public InvalidFieldExpressionException(ErrorCodesClient code, String message) {
*
* @param path
* current field expression
+ * @param cause
+ * cause of the error
*/
public static void throwInvalidField(String path, String cause) {
throw new InvalidFieldExpressionException(INVALID_EXPRESSION,
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/UnexpectedDataAPIResponseException.java b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/UnexpectedDataAPIResponseException.java
index 41a90899..dc3eebe5 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/UnexpectedDataAPIResponseException.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/exceptions/UnexpectedDataAPIResponseException.java
@@ -75,5 +75,17 @@ public UnexpectedDataAPIResponseException(Command cmd, DataAPIResponse res, Stri
this.command = cmd;
this.response = res;
}
+
+ /**
+ * Constructs a new exception with the specified command that triggered the error,
+ * the API response received, and a custom error message.
+ *
+ * @param msg The detailed error message explaining the nature of the fault.
+ */
+ public UnexpectedDataAPIResponseException(String msg) {
+ super(DEFAULT_ERROR_CODE, msg);
+ this.command = null;
+ this.response = null;
+ }
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/Table.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/Table.java
index a60ece8b..c8801114 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/Table.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/Table.java
@@ -794,6 +794,16 @@ public TableFindCursor findAll() {
return find(null, new TableFindOptions());
}
+ /**
+ * Search for a Page with no projection.
+ *
+ * @param filter
+ * the query filter
+ * @param options
+ * options of find one
+ * @return
+ * the Page to iterate over the results
+ */
public Page findPage(Filter filter, TableFindOptions options) {
return findPage(filter, options, getRowClass());
}
@@ -816,9 +826,16 @@ public Page findPage(Filter filter, TableFindOptions options) {
* This list, along with the maximum page size and the next page state, is used to construct the {@link Page} object returned by the method.
*
*
- * @param filter The filter criteria used to select rows from the table.
- * @param options The {@link CollectionFindOptions} providing additional query parameters, such as sorting and pagination.
- * @return A {@link Page} object containing the rows that match the query, along with pagination information.
+ * @param
+ * projection for the new type
+ * @param newRowType
+ * the class representing the row type for the result; must not be {@code null}.
+ * @param filter
+ * The filter criteria used to select rows from the table.
+ * @param options
+ * The {@link CollectionFindOptions} providing additional query parameters, such as sorting and pagination.
+ * @return
+ * A {@link Page} object containing the rows that match the query, along with pagination information.
*/
public Page findPage(Filter filter, TableFindOptions options, Class newRowType) {
Command findCommand = Command
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/cursor/TableFindCursor.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/cursor/TableFindCursor.java
index eda34bdf..560f7bbd 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/cursor/TableFindCursor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/cursor/TableFindCursor.java
@@ -24,12 +24,14 @@
import com.datastax.astra.client.core.query.Filter;
import com.datastax.astra.client.core.query.Projection;
import com.datastax.astra.client.core.query.Sort;
+import com.datastax.astra.client.core.vector.DataAPIVector;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.options.TableFindOptions;
import com.datastax.astra.internal.command.AbstractCursor;
import lombok.Getter;
import java.util.ArrayList;
+import java.util.Optional;
/**
* Implementation of a cursor across the find items
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexColumnDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexColumnDefinition.java
index 194c4f3f..6fba8daa 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexColumnDefinition.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexColumnDefinition.java
@@ -25,15 +25,32 @@
import lombok.Data;
import lombok.NoArgsConstructor;
+/**
+ * Represents a column definition for a table index, including the column's name and type.
+ * This class is designed for use in scenarios such as serialization/deserialization with libraries
+ * like Jackson and for method chaining in fluent-style APIs.
+ */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TableIndexColumnDefinition {
+ /**
+ * The name of the column.
+ */
String name;
+ /**
+ * The type of the column.
+ */
TableIndexMapTypes type;
+ /**
+ * Constructor that accepts a column name.
+ *
+ * @param name
+ * the name of the column.
+ */
public TableIndexColumnDefinition(String name) {
this.name = name;
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDefinition.java
index 8776575e..806cc50c 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDefinition.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDefinition.java
@@ -34,6 +34,8 @@
*
* Subclasses should extend this abstract class to implement specific types of index definitions.
*
+ *
+ * @param the type of options (vector, normal) for index definition.
*/
@Getter
public abstract class TableIndexDefinition {
@@ -60,16 +62,19 @@ public abstract class TableIndexDefinition {
protected final Function> constructor;
/**
- * Constructor.
+ * Constructs a new instance of {@code TableIndexDefinition} with the specified constructor function.
+ *
+ * @param constructor the constructor function for creating new instances of the subclass.
*/
protected TableIndexDefinition(Function> constructor) {
this.constructor = constructor;
}
/**
- * Invoke the constructor function to create a new instance of the subclass.
- * @param updater
- * @return
+ * Maps the current instance to a new instance with updated properties.
+ *
+ * @param updater a consumer function that updates the properties of the new instance.
+ * @return a new instance with the updated properties.
*/
protected TableIndexDefinition mapImpl(Consumer> updater) {
TableIndexDefinition newInstance = constructor.apply(this.options);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDescriptor.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDescriptor.java
index 309b8296..ef442dc9 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDescriptor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexDescriptor.java
@@ -30,6 +30,12 @@
import java.util.function.Consumer;
import java.util.function.Function;
+/**
+ * Represents a descriptor for a table index, including the table's name and associated index options.
+ *
+ * @param
+ * the type of index definition.
+ */
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
@@ -63,11 +69,11 @@ public abstract class TableIndexDescriptor>
@JsonIgnore
protected final Function> constructor;
- /**
- * Default constructor for serialization/deserialization.
- */
/**
* Constructor that accepts a function for instance creation.
+ *
+ * @param constructor
+ * the function to create a new instance of the subclass.
*/
protected TableIndexDescriptor(Function> constructor) {
this.constructor = constructor;
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexMapTypes.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexMapTypes.java
index 2f4ed8d2..c3d7af4a 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexMapTypes.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableIndexMapTypes.java
@@ -22,6 +22,11 @@
import lombok.Getter;
+/**
+ * Enum representing the types of map indexes in a table.
+ * This enum is designed for use in scenarios such as serialization/deserialization with libraries
+ * like Jackson and for method chaining in fluent-style APIs.
+ */
@Getter
public enum TableIndexMapTypes {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableRegularIndexDescriptor.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableRegularIndexDescriptor.java
index 8959a513..edc06d33 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableRegularIndexDescriptor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableRegularIndexDescriptor.java
@@ -29,6 +29,9 @@
*/
public class TableRegularIndexDescriptor extends TableIndexDescriptor {
+ /**
+ * The default name for the index.
+ */
public TableRegularIndexDescriptor() {
super(TableRegularIndexDescriptor::new);
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinition.java
index a295cef7..2a17abbc 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinition.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinition.java
@@ -58,21 +58,48 @@ protected TableTextIndexDefinition(TableTextIndexDefinitionOptions options) {
this.options = options;
}
+ /**
+ * Setter for the column name
+ *
+ * @param column the name of the column to index.
+ * @return self reference
+ */
@Override
public TableTextIndexDefinition column(String column) {
return (TableTextIndexDefinition) super.column(column);
}
+ /**
+ * Setter for the column name
+ *
+ * @param column the name of the column to index.
+ * @param type the type of the index.
+ * @return self reference
+ */
@Override
public TableTextIndexDefinition column(String column, TableIndexMapTypes type) {
return (TableTextIndexDefinition) super.column(column, type);
}
+ /**
+ * Setter for the options
+ *
+ * @param options the options of the index.
+ * @return self reference
+ */
@Override
public TableTextIndexDefinition options(TableTextIndexDefinitionOptions options) {
return (TableTextIndexDefinition) super.options(options);
}
+ /**
+ * Setter for the analyzer
+ *
+ * @param analyzer
+ * Value for analyzer
+ * @return
+ * Self reference
+ */
public TableTextIndexDefinition analyzer(Analyzer analyzer) {
if (options == null) {
this.options = new TableTextIndexDefinitionOptions();
@@ -81,6 +108,14 @@ public TableTextIndexDefinition analyzer(Analyzer analyzer) {
return this;
}
+ /**
+ * Setter for the analyzer with a type
+ *
+ * @param analyzerTypes
+ * Type of the analyzer
+ * @return
+ * Self reference
+ */
public TableTextIndexDefinition analyzer(AnalyzerTypes analyzerTypes) {
if (options == null) {
this.options = new TableTextIndexDefinitionOptions();
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinitionOptions.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinitionOptions.java
index 871c14ab..c7427c4f 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinitionOptions.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDefinitionOptions.java
@@ -24,9 +24,17 @@
import com.datastax.astra.client.core.lexical.AnalyzerTypes;
import lombok.Data;
+/**
+ * Represents the options for a text index definition in a table.
+ * This class is designed for use in scenarios such as serialization/deserialization with libraries
+ * like Jackson and for method chaining in fluent-style APIs.
+ */
@Data
public class TableTextIndexDefinitionOptions {
+ /**
+ * The analyzer to use for the text index.
+ */
Analyzer analyzer;
/**
@@ -35,11 +43,27 @@ public class TableTextIndexDefinitionOptions {
public TableTextIndexDefinitionOptions() {
}
+ /**
+ * Constructor that accepts an analyzer.
+ *
+ * @param analyzer
+ * the analyzer to use.
+ * @return
+ * the current instance of {@link TableTextIndexDefinitionOptions}.
+ */
public TableTextIndexDefinitionOptions analyzer(Analyzer analyzer) {
this.analyzer = analyzer;
return this;
}
+ /**
+ * Constructor that accepts an analyzer type.
+ *
+ * @param analyzerType
+ * the analyzer type to use.
+ * @return
+ * the current instance of {@link TableTextIndexDefinitionOptions}.
+ */
public TableTextIndexDefinitionOptions analyzer(AnalyzerTypes analyzerType) {
this.analyzer = new Analyzer(analyzerType);
return this;
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDescriptor.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDescriptor.java
index c333a57e..648fc96d 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDescriptor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableTextIndexDescriptor.java
@@ -27,6 +27,9 @@
*/
public class TableTextIndexDescriptor extends TableIndexDescriptor {
+ /**
+ * The default name for the index.
+ */
public TableTextIndexDescriptor() {
super(TableTextIndexDescriptor::new);
}
@@ -41,11 +44,27 @@ protected TableTextIndexDescriptor(TableTextIndexDefinition definition) {
this.definition = definition;
}
+ /**
+ * Adds a name to the index.
+ *
+ * @param name
+ * the name of the table.
+ * @return
+ * the current instance of {@link TableTextIndexDescriptor}.
+ */
@Override
public TableTextIndexDescriptor name(String name) {
return (TableTextIndexDescriptor) super.name(name);
}
+ /**
+ * Adds a definitions to the index.
+ *
+ * @param def
+ * the definition of the index.
+ * @return
+ * the current instance of {@link TableTextIndexDescriptor}.
+ */
@Override
public TableTextIndexDescriptor definition(TableTextIndexDefinition def) {
return (TableTextIndexDescriptor) super.definition(def);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableVectorIndexDescriptor.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableVectorIndexDescriptor.java
index a906b343..512fda42 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableVectorIndexDescriptor.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/indexes/TableVectorIndexDescriptor.java
@@ -30,6 +30,9 @@
@Getter @Setter
public class TableVectorIndexDescriptor extends TableIndexDescriptor {
+ /**
+ * The default name for the index.
+ */
public TableVectorIndexDescriptor() {
super(TableVectorIndexDescriptor::new);
}
@@ -44,6 +47,7 @@ protected TableVectorIndexDescriptor(TableVectorIndexDefinition definition) {
this.definition = definition;
}
+
@Override
public TableVectorIndexDescriptor name(String name) {
return (TableVectorIndexDescriptor) super.name(name);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/rows/Row.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/rows/Row.java
index ce8e61b5..bff26e5d 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/rows/Row.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/definition/rows/Row.java
@@ -24,6 +24,7 @@
import com.datastax.astra.client.core.DataAPIKeywords;
import com.datastax.astra.client.core.hybrid.Hybrid;
import com.datastax.astra.client.core.vector.DataAPIVector;
+import com.datastax.astra.client.exceptions.UnexpectedDataAPIResponseException;
import com.datastax.astra.client.tables.definition.TableDuration;
import com.datastax.astra.internal.serdes.DataAPISerializer;
import com.datastax.astra.internal.serdes.tables.RowSerializer;
@@ -44,12 +45,14 @@
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
@@ -233,6 +236,8 @@ public Row addVectorize(final String key, final String value) {
*
* @param hybrid
* hybrid object to be added
+ * @return
+ * self reference
*/
@BetaPreview
public Row addHybrid(Hybrid hybrid) {
@@ -758,8 +763,25 @@ public Long getBigInt(final String key) {
* @return the value as a DataAPIVector, which may be null
* @throws ClassCastException if the value is not a DataAPIVector
*/
+ @SuppressWarnings("unchecked")
public DataAPIVector getVector(final String key) {
- return get(key, DataAPIVector.class);
+ Object o = get(key);
+ // Get a vector from a list of doubles
+ if (o instanceof DataAPIVector) {
+ return ((DataAPIVector) o);
+ } else if (o instanceof ArrayList> list && !list.isEmpty() && list.get(0) instanceof Double) {
+ ArrayList a = (ArrayList) list;
+ float[] floatArray = new float[a.size()];
+ for (int i = 0; i < a.size(); i++) {
+ floatArray[i] = a.get(i).floatValue();
+ }
+ return new DataAPIVector(floatArray);
+ } else if (o instanceof float[] array) {
+ // Get a vector from a float array
+ return new DataAPIVector(array);
+ }
+ throw new UnexpectedDataAPIResponseException("Could not parse " + key + " of type " + o.getClass().getName() +
+ " to a DataAPIVector. Expected a list of Double, a float array or binary data");
}
/**
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/ColumnVector.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/ColumnVector.java
index 99748667..f1b38d5c 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/ColumnVector.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/ColumnVector.java
@@ -61,19 +61,39 @@
*/
SimilarityMetric metric() default SimilarityMetric.COSINE;
+ /**
+ * Specifies source model for the column. Defaults to "other".
+ *
+ * @return the source model value or "other" if not set
+ */
String sourceModel() default "other";
/**
- * Specifies the column's index. Defaults to -1, indicating no index.
+ * Specifies the provider for the column. Defaults to an empty string.
*
- * @return the index value or -1 if not set
+ * @return the provider value or an empty string if not set
*/
String provider() default "";
+ /**
+ * Specifies the model name for the column. Defaults to an empty string.
+ *
+ * @return the model name value or an empty string if not set
+ */
String modelName() default "";
+ /**
+ * List some authentication information for the column. Defaults to an empty array.
+ *
+ * @return the index value or -1 if not set
+ */
KeyValue[] authentication() default {};
+ /**
+ * Specifies the parameters for authentication
+ *
+ * @return a key value array
+ */
KeyValue[] parameters() default {};
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/KeyValue.java b/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/KeyValue.java
index 8892989c..8ba73397 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/KeyValue.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/client/tables/mapping/KeyValue.java
@@ -23,8 +23,23 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+/**
+ * Key value annotation.
+ */
@Retention(RetentionPolicy.RUNTIME)
public @interface KeyValue {
+
+ /**
+ * Key.
+ *
+ * @return key
+ */
String key();
+
+ /**
+ * Value.
+ *
+ * @return value
+ */
String value();
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/command/AbstractCommandRunner.java b/astra-db-java/src/main/java/com/datastax/astra/internal/command/AbstractCommandRunner.java
index 6a869c84..9a76693a 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/command/AbstractCommandRunner.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/command/AbstractCommandRunner.java
@@ -313,7 +313,6 @@ public DataAPIResponse runCommand(Command command, BaseOptions> overridingOpti
overClientOptions.getEmbeddingHeadersProvider().getHeaders().forEach(builder::header);
}
if (overClientOptions.getRerankingHeadersProvider() != null) {
- System.out.println("ADDING RERANKING K");
overClientOptions.getRerankingHeadersProvider().getHeaders().forEach(builder::header);
}
if (overClientOptions.getDatabaseAdditionalHeaders() != null) {
@@ -324,7 +323,6 @@ public DataAPIResponse runCommand(Command command, BaseOptions> overridingOpti
}
}
-
HttpRequest request = builder.build();
executionInfo.withSerializer(serializer);
executionInfo.withRequestHeaders(request.headers().map());
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/command/CursorError.java b/astra-db-java/src/main/java/com/datastax/astra/internal/command/CursorError.java
index 14deb045..92ab81fd 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/command/CursorError.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/command/CursorError.java
@@ -23,14 +23,25 @@
import com.datastax.astra.client.core.paging.CursorState;
import com.datastax.astra.client.exceptions.DataAPIException;
+/**
+ * Exception thrown when an error occurs while using a cursor.
+ */
public class CursorError extends DataAPIException {
- // The underlying cursor which caused this error.
+ /** The default error code for cursor errors. */
public final AbstractCursor, ?> cursor;
- // The state of the cursor when the error occurred.
+ /** The state of the cursor when the error occurred. */
public final CursorState state;
+ /**
+ * Constructor.
+ *
+ * @param message
+ * the error message.
+ * @param cursor
+ * the cursor that caused the error.
+ */
public CursorError(String message, AbstractCursor, ?> cursor) {
super(DEFAULT_ERROR_CODE, message);
this.cursor = cursor;
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/reflection/EntityBeanDefinition.java b/astra-db-java/src/main/java/com/datastax/astra/internal/reflection/EntityBeanDefinition.java
index ba138cde..d67fc6f2 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/reflection/EntityBeanDefinition.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/reflection/EntityBeanDefinition.java
@@ -240,6 +240,16 @@ public Map getPartitionSort() {
return cc;
}
+ /**
+ * List all vector index definitions for the given table name and class.
+ *
+ * @param tableName
+ * the table name
+ * @param clazz
+ * the class
+ * @return
+ * a list of vector index definitions
+ */
public static List listVectorIndexDefinitions(String tableName, Class> clazz) {
EntityBeanDefinition> bean = new EntityBeanDefinition<>(clazz);
if (Utils.hasLength(bean.getName()) && !bean.getName().equals(tableName)) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonCalendarDeserializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonCalendarDeserializer.java
index 3f00e08c..db8d0ced 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonCalendarDeserializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonCalendarDeserializer.java
@@ -45,9 +45,6 @@ public EJsonCalendarDeserializer() {
public Calendar deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
- if (null == node.get("$date")) {
- throw new IllegalArgumentException("Cannot convert the expression as an Calendar " + node);
- }
long timestamp = node.get("$date").asLong();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonDateDeserializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonDateDeserializer.java
index 291a6820..ad2b0b34 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonDateDeserializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonDateDeserializer.java
@@ -45,9 +45,6 @@ public EJsonDateDeserializer() {
public Date deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
- if (null == node.get("$date")) {
- throw new IllegalArgumentException("Cannot convert the expression as an Date " + node);
- }
long timestamp = node.get("$date").asLong();
return new Date(timestamp);
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonInstantDeserializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonInstantDeserializer.java
index a91b3998..0a8759a4 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonInstantDeserializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/EJsonInstantDeserializer.java
@@ -45,9 +45,6 @@ public EJsonInstantDeserializer() {
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
- if (null == node.get("$date")) {
- throw new IllegalArgumentException("Cannot convert the expression as an Instant " + node);
- }
long timestamp = node.get("$date").asLong();
return Instant.ofEpochMilli(timestamp);
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/HybridLimitsSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/HybridLimitsSerializer.java
index aafd1b81..80921d94 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/HybridLimitsSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/collections/HybridLimitsSerializer.java
@@ -32,15 +32,16 @@
/**
* Serializer for TableIndexColumnDefinition.
- *
- * {"column": "name"}
- *
*/
public class HybridLimitsSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
public HybridLimitsSerializer() {
}
+ /** {@inheritDoc} */
@Override
public void serialize(HybridLimits def, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (def == null) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/AnalyzerSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/AnalyzerSerializer.java
index 5055c111..6a061269 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/AnalyzerSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/AnalyzerSerializer.java
@@ -37,6 +37,13 @@
*/
public class AnalyzerSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
+ public AnalyzerSerializer() {
+ super();
+ }
+
@Override
public void serialize(Analyzer analyzer, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (analyzer == null) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/HybridSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/HybridSerializer.java
index 2deeca08..7548320f 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/HybridSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/HybridSerializer.java
@@ -34,6 +34,13 @@
*/
public class HybridSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
+ public HybridSerializer() {
+ super();
+ }
+
@Override
public void serialize(Hybrid value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String vectorize = value.getDoc().getVectorize().orElse(null);
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/LexicalSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/LexicalSerializer.java
index 9c801a80..27fd64a4 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/LexicalSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/LexicalSerializer.java
@@ -34,6 +34,13 @@
*/
public class LexicalSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
+ public LexicalSerializer() {
+ super();
+ }
+
@Override
public void serialize(Lexical value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value.getText() != null) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/VectorizeSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/VectorizeSerializer.java
index d5ef5a74..e78488b2 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/VectorizeSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/core/VectorizeSerializer.java
@@ -32,6 +32,13 @@
*/
public class VectorizeSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
+ public VectorizeSerializer() {
+ super();
+ }
+
@Override
public void serialize(Vectorize value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value.getSetPassage() == null || value.getSetPassage().isEmpty()) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/tables/TableIndexColumnDefinitionSerializer.java b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/tables/TableIndexColumnDefinitionSerializer.java
index d1f55846..27a576c2 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/tables/TableIndexColumnDefinitionSerializer.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/serdes/tables/TableIndexColumnDefinitionSerializer.java
@@ -36,9 +36,13 @@
*/
public class TableIndexColumnDefinitionSerializer extends JsonSerializer {
+ /**
+ * Default constructor
+ */
public TableIndexColumnDefinitionSerializer() {
}
+ /** {@inheritDoc} */
@Override
public void serialize(TableIndexColumnDefinition def, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (def == null) {
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/utils/BetaPreview.java b/astra-db-java/src/main/java/com/datastax/astra/internal/utils/BetaPreview.java
index 89c4b7b9..b3340cd4 100644
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/utils/BetaPreview.java
+++ b/astra-db-java/src/main/java/com/datastax/astra/internal/utils/BetaPreview.java
@@ -33,5 +33,12 @@
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
@Deprecated
public @interface BetaPreview {
+
+ /**
+ * Message to be displayed when the feature is used.
+ *
+ * @return message
+ * current depracation message
+ */
String value() default "This feature is in beta and might undergo signature or behaviour changes in the future.";
}
diff --git a/astra-db-java/src/main/java/com/datastax/astra/internal/utils/FieldPathSegment.java b/astra-db-java/src/main/java/com/datastax/astra/internal/utils/FieldPathSegment.java
deleted file mode 100644
index 99d2cfb4..00000000
--- a/astra-db-java/src/main/java/com/datastax/astra/internal/utils/FieldPathSegment.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.datastax.astra.internal.utils;
-
-/*-
- * #%L
- * Data API Java Client
- * --
- * Copyright (C) 2024 - 2025 DataStax
- * --
- * Licensed under the Apache License, Version 2.0
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * #L%
- */
-
-
-import lombok.Getter;
-
-@Getter
-public class FieldPathSegment {
-
- private final String strValue;
-
- private final Integer idxValue;
-
- public FieldPathSegment(String strValue) {
- Assert.notNull(strValue, "strValue cannot be null");
- this.strValue = strValue;
- this.idxValue = null;
- }
-
- public FieldPathSegment(Integer idxValue) {
- Assert.notNull(idxValue, "idxValue cannot be null");
- this.idxValue = idxValue;
- this.strValue = null;
- }
-
- public static FieldPathSegment of(String strValue) {
- return new FieldPathSegment(strValue);
- }
-
- public static FieldPathSegment of(Integer idxValue) {
- return new FieldPathSegment(idxValue);
- }
-
- public boolean isString() {
- return strValue != null;
- }
-
-
-}
diff --git a/astra-db-java/src/test/java/com/datastax/astra/test/integration/AbstractDatabaseAdminITTest.java b/astra-db-java/src/test/java/com/datastax/astra/test/integration/AbstractDatabaseAdminITTest.java
index 0c7a05ee..a0b46f21 100644
--- a/astra-db-java/src/test/java/com/datastax/astra/test/integration/AbstractDatabaseAdminITTest.java
+++ b/astra-db-java/src/test/java/com/datastax/astra/test/integration/AbstractDatabaseAdminITTest.java
@@ -3,7 +3,9 @@
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.admin.DatabaseAdmin;
import com.datastax.astra.client.core.vectorize.EmbeddingProvider;
+import com.datastax.astra.client.databases.commands.options.CreateKeyspaceOptions;
import com.datastax.astra.client.databases.commands.results.FindEmbeddingProvidersResult;
+import com.datastax.astra.client.databases.definition.keyspaces.KeyspaceDefinition;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
@@ -90,7 +92,8 @@ void shouldKeyNamespaceDefault() throws InterruptedException {
.getKeyspace()).isEqualTo("nsx");
if (!getDatabaseAdmin().keyspaceExists("nsx2")) {
- getDatabaseAdmin().createKeyspace("nsx2", true);
+
+ getDatabaseAdmin().createKeyspace(new KeyspaceDefinition().name("nsx2"), new CreateKeyspaceOptions().updateDBKeyspace(true));
while (!getDatabaseAdmin().keyspaceExists("nsx2")) {
Thread.sleep(1000);
}
@@ -100,7 +103,7 @@ void shouldKeyNamespaceDefault() throws InterruptedException {
// Surface
final DatabaseAdmin dbAdmin2 = getDatabaseAdmin();
assertThatExceptionOfType(IllegalArgumentException.class)
- .isThrownBy(() -> dbAdmin2.createKeyspace(null))
+ .isThrownBy(() -> dbAdmin2.createKeyspace((String) null))
.withMessage("Parameter 'keyspaceName' should be null nor empty");
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> dbAdmin2.createKeyspace(""))
diff --git a/astra-db-java/src/test/java/com/datastax/astra/test/integration/astra/DemoAstraDevFindAndRerank.java b/astra-db-java/src/test/java/com/datastax/astra/test/integration/astra/DemoAstraDevFindAndRerank.java
new file mode 100644
index 00000000..592b3227
--- /dev/null
+++ b/astra-db-java/src/test/java/com/datastax/astra/test/integration/astra/DemoAstraDevFindAndRerank.java
@@ -0,0 +1,294 @@
+package com.datastax.astra.test.integration.astra;
+
+import com.datastax.astra.client.DataAPIClient;
+import com.datastax.astra.client.collections.Collection;
+import com.datastax.astra.client.collections.commands.options.CollectionFindAndRerankOptions;
+import com.datastax.astra.client.collections.commands.options.CollectionInsertManyOptions;
+import com.datastax.astra.client.collections.definition.CollectionDefinition;
+import com.datastax.astra.client.collections.definition.documents.Document;
+import com.datastax.astra.client.core.DataAPIKeywords;
+import com.datastax.astra.client.core.headers.EmbeddingAPIKeyHeaderProvider;
+import com.datastax.astra.client.core.headers.EmbeddingHeadersProvider;
+import com.datastax.astra.client.core.headers.RerankingAPIKeyHeaderProvider;
+import com.datastax.astra.client.core.hybrid.Hybrid;
+import com.datastax.astra.client.core.lexical.Analyzer;
+import com.datastax.astra.client.core.lexical.LexicalOptions;
+import com.datastax.astra.client.core.options.DataAPIClientOptions;
+import com.datastax.astra.client.core.query.Projection;
+import com.datastax.astra.client.core.query.Sort;
+import com.datastax.astra.client.core.rerank.CollectionRerankOptions;
+import com.datastax.astra.client.core.rerank.RerankedResult;
+import com.datastax.astra.client.core.rerank.RerankServiceOptions;
+import com.datastax.astra.client.core.vector.SimilarityMetric;
+import com.datastax.astra.client.core.vector.VectorOptions;
+import com.datastax.astra.client.core.vectorize.VectorServiceOptions;
+import com.datastax.astra.client.databases.Database;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+import static com.datastax.astra.client.DataAPIDestination.ASTRA_DEV;
+import static com.datastax.astra.client.core.lexical.AnalyzerTypes.STANDARD;
+import static com.dtsx.astra.sdk.db.domain.CloudProviderType.GCP;
+
+@Slf4j
+public class DemoAstraDevFindAndRerank {
+
+ public static final String ASTRA_DB_TOKEN = System.getenv("ASTRA_DB_APPLICATION_TOKEN_DEV");
+ public static final String DATABASE_DEMO_NAME = "demo_charter";
+
+ public static final String ASTRA_DB_ENDPOINT = "https://9e0ff165-666d-4a69-b5b7-727d6cd77092-us-central1.apps.astra-dev.datastax.com";
+ public static final String OPEN_API_KEY = System.getenv("OPENAI_API_KEY");
+
+ /**
+ * Create a DataAPIClient for Astra DEV.
+ */
+ private DataAPIClient getDataApiClient() {
+ DataAPIClientOptions options = new DataAPIClientOptions()
+ .destination(ASTRA_DEV)
+ .rerankAPIKey(ASTRA_DB_TOKEN)
+ .embeddingAPIKey(OPEN_API_KEY)
+ .logRequests();
+ return new DataAPIClient(ASTRA_DB_TOKEN, options);
+ }
+
+ /**
+ * Access DB from its endpoints (regular way)
+ */
+ private Database getDatabase() {
+ // Alternatively, you can use the following code to get the database:
+ return getDataApiClient().getAdmin()
+ .createDatabase(DATABASE_DEMO_NAME, GCP, "us-central1")
+ .getDatabase();
+ //return getDataApiClient().getDatabase(ASTRA_DB_ENDPOINT);
+ }
+
+ @Test
+ public void should_list_db() {
+ getDataApiClient()
+ .getAdmin()
+ .listDatabases()
+ .forEach(db -> {
+ log.info("DB: name={}, status={}, cloud={}, region={}",
+ db.getName(),
+ db.getRawDevopsResponse().getStatus(),
+ db.getCloudProvider(),
+ db.getRegion());
+ });
+ }
+
+ @Test
+ public void should_find_rerank_providers() {
+ getDatabase()
+ .getDatabaseAdmin()
+ .findRerankingProviders()
+ .getRerankingProviders()
+ .get("nvidia")
+ .getModels().forEach(model -> {
+ System.out.println("Model: " + model.getName() + " - " + model.getUrl());
+ });
+ }
+
+ @Test
+ public void should_find_embedding_providers() {
+ getDatabase().getDatabaseAdmin()
+ .findEmbeddingProviders()
+ .getEmbeddingProviders()
+ .get("nvidia")
+ .getModels()
+ .forEach(model -> {
+ System.out.println("Model: " + model.getName() + " - " + model.getVectorDimension());
+ });
+ }
+
+ @Test
+ public void should_create_collection_default() {
+ // Create Collection
+ getDatabase().createCollection("c_first");
+
+ CollectionDefinition def = getDatabase()
+ .getCollection("c_first")
+ .getDefinition();
+ System.out.println("--------------------------------");
+ System.out.println(JsonUtils.marshall(def));
+ }
+
+ @Test
+ public void should_create_collection_reranking() {
+
+ CollectionDefinition def = new CollectionDefinition();
+
+ // Vector
+ VectorServiceOptions vectorService = new VectorServiceOptions()
+ .provider("nvidia")
+ .modelName("NV-Embed-QA");
+ VectorOptions vectorOptions = new VectorOptions()
+ .dimension(1024)
+ .metric(SimilarityMetric.COSINE.getValue())
+ .service(vectorService);
+ def.vector(vectorOptions);
+
+ // Lexical
+ LexicalOptions lexicalOptions = new LexicalOptions()
+ .enabled(true)
+ .analyzer(new Analyzer(STANDARD));
+ def.lexical(lexicalOptions);
+
+ // Rerank
+ RerankServiceOptions rerankService = new RerankServiceOptions()
+ .modelName("nvidia/llama-3.2-nv-rerankqa-1b-v2")
+ .provider("nvidia");
+ CollectionRerankOptions rerankOptions = new CollectionRerankOptions()
+ .enabled(true)
+ .service(rerankService);
+ def.rerank(rerankOptions);
+
+ getDatabase().createCollection("c_find_rerank", def);
+ }
+
+ @Test
+ public void should_populate_collection() throws IOException {
+
+ Collection myCol = getDatabase()
+ .getCollection("c_find_rerank");
+
+ myCol.deleteAll();
+
+ List docs = Files
+ .readAllLines(Paths.get("src/test/resources/philosopher-quotes.csv"))
+ .stream().map(line -> {
+ String[] chunks = line.split(",");
+ String quote = chunks[1].replace("\"", "");
+ return new Document()
+ .append("author", chunks[0])
+ .append("quote", quote)
+ .append("tags", chunks.length > 2 ? chunks[2].split(";") : new String[0])
+ //.hybrid(new Hybrid(quote))
+ //.hybrid(new Hybrid().lexical(quote).vectorize(quote))
+ .lexical(quote).vectorize(quote);
+ }).toList();
+
+ CollectionInsertManyOptions beGentleWihAstraDev = new CollectionInsertManyOptions()
+ .concurrency(3).chunkSize(20);
+ myCol.insertMany(docs, beGentleWihAstraDev);
+ }
+
+ @Test
+ public void should_run_find_and_rerank() throws IOException {
+ CollectionFindAndRerankOptions farrOptions = new CollectionFindAndRerankOptions()
+ .projection(Projection.include("$vectorize", "_id", "quote", "author"))
+
+
+ .sort(Sort.hybrid(new Hybrid("We struggle all in life")))
+
+
+
+ .rerankingAuthProvider(new RerankingAPIKeyHeaderProvider(ASTRA_DB_TOKEN))
+ .embeddingAuthProvider(new EmbeddingAPIKeyHeaderProvider(ASTRA_DB_TOKEN))
+ .includeScores(true)
+ .limit(10)
+ .hybridLimits(10);
+
+ getDatabase().getCollection("c_find_rerank")
+ .findAndRerank(null, farrOptions)
+ .forEach(res -> {
+ System.out.println(res.getDocument());
+ System.out.println(res.getScores());
+ });
+ }
+
+ @Test
+ public void should_test_with_openai() throws IOException {
+ Collection openAiCollection = getDatabase()
+ .createCollection("c_openai", new CollectionDefinition()
+ .vector(new VectorOptions()
+ .dimension(1536)
+ .metric(SimilarityMetric.COSINE.getValue())
+ .service(new VectorServiceOptions()
+ .provider("openai")
+ .modelName("text-embedding-3-small")))
+ .lexical(STANDARD)
+ .rerank(new CollectionRerankOptions()
+ .service(new RerankServiceOptions()
+ .modelName("nvidia/llama-3.2-nv-rerankqa-1b-v2")
+ .provider("nvidia"))));
+
+ // INGEST
+ List docs = Files.readAllLines(Paths.get("src/test/resources/philosopher-quotes.csv"))
+ .stream().map(line -> {
+ String[] chunks = line.split(",");
+ String quote = chunks[1].replace("\"", "");
+ return new Document()
+ .append("author", chunks[0])
+ .append("quote", quote)
+ // no insert why hybrid
+ .lexical(quote)
+ .vectorize(quote);
+ }).toList();
+ EmbeddingHeadersProvider authEmbedding =
+ new EmbeddingAPIKeyHeaderProvider(System.getenv("OPENAI_API_KEY"));
+ openAiCollection.insertMany(docs, new CollectionInsertManyOptions()
+ .concurrency(3)
+ .chunkSize(10)
+ .embeddingAuthProvider(authEmbedding));
+
+ // SEARCh
+ // Build Query
+ CollectionFindAndRerankOptions farrOptions = new CollectionFindAndRerankOptions()
+ .projection(Projection.include("$vectorize", "_id", "quote", "author"))
+ .sort(Sort.hybrid(new Hybrid("We struggle all in life")))
+ .rerankingAuthProvider(new RerankingAPIKeyHeaderProvider(ASTRA_DB_TOKEN))
+ .embeddingAuthProvider(authEmbedding)
+ .includeScores(true)
+ .limit(10)
+ .hybridLimits(10);
+
+ // Execute the command
+ openAiCollection.findAndRerank(null, farrOptions)
+ .stream()
+ .forEach(res -> {
+ System.out.println(res.getDocument());
+ System.out.println(res.getScores());
+ });
+ }
+
+ @Test
+ public void should_query_collection_bring_my_own_vector() {
+ Collection myCol = getDatabase().getCollection("c_openai");
+
+ // Bring your own vector
+ Hybrid hybridSort = new Hybrid().vector(
+ OpenAiEmbeddingModel
+ .builder().apiKey(OPEN_API_KEY)
+ .modelName("text-embedding-3-small")
+ .build().embed("We struggle all in life")
+ .content().vector())
+ .lexical("struggle life");
+
+ // Build Query
+ CollectionFindAndRerankOptions farrOptions = new CollectionFindAndRerankOptions()
+ .projection(Projection.include("$vectorize", "_id", "quote", "author"))
+ .rerankingAuthProvider(new RerankingAPIKeyHeaderProvider(ASTRA_DB_TOKEN))
+ .sort(Sort.hybrid(hybridSort))
+ // This is the default
+ .rerankOn(DataAPIKeywords.VECTORIZE.getKeyword())
+ // Rerank query
+ .rerankQuery("We struggle all in life")
+ .includeScores(true)
+ .limit(10)
+ .hybridLimits(20);
+
+ // Run the query
+ List> result = myCol.findAndRerank(farrOptions).toList();
+ Assertions.assertNotNull(result);
+ Assertions.assertFalse(result.isEmpty());
+ System.out.println("Result: " + result.size());
+ }
+}
\ No newline at end of file
diff --git a/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_02_Database_ITTest.java b/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_02_Database_ITTest.java
index 4a8d8135..9d6f0c21 100644
--- a/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_02_Database_ITTest.java
+++ b/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_02_Database_ITTest.java
@@ -7,10 +7,13 @@
import com.datastax.astra.client.core.http.HttpClientOptions;
import com.datastax.astra.client.core.options.DataAPIClientOptions;
import com.datastax.astra.client.core.auth.UsernamePasswordTokenProvider;
+import com.datastax.astra.client.core.options.TimeoutOptions;
+import com.datastax.astra.client.databases.DatabaseOptions;
import com.datastax.astra.client.exceptions.DataAPIException;
import com.datastax.astra.client.core.commands.Command;
import com.datastax.astra.client.collections.definition.documents.Document;
import com.datastax.astra.client.core.http.HttpProxy;
+import com.datastax.astra.internal.command.LoggingCommandObserver;
import com.datastax.astra.test.integration.AbstractDatabaseTest;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -18,6 +21,7 @@
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import java.io.IOException;
+import java.time.Duration;
import java.util.Set;
import static com.datastax.astra.client.DataAPIClients.DEFAULT_ENDPOINT_LOCAL;
@@ -44,6 +48,13 @@ void shouldRunInvalidCommand() {
} catch(DataAPIException dat) {
assertThat(dat.getMessage()).contains("COMMAND_UNKNOWN");;
}
+
+ getDataApiClient().getDatabase("endpoints", new DatabaseOptions()
+ .keyspace("sss").token("...")
+ .dataAPIClientOptions(new DataAPIClientOptions()
+ .timeoutOptions(new TimeoutOptions()
+ .requestTimeout(Duration.ofSeconds(30)))));
+
}
@Test
@@ -72,6 +83,7 @@ void shouldInitializeHttpClientWithProxy() throws IOException {
// Moving to admin I add a HTTP PROXY
.getDatabaseAdmin(new AdminOptions()
.dataAPIClientOptions(new DataAPIClientOptions()
+ .timeoutOptions(new TimeoutOptions())
.httpClientOptions(new HttpClientOptions()
.httpProxy(new HttpProxy(mockWebServer.getHostName(), mockWebServer.getPort()))
)
@@ -89,6 +101,7 @@ void shouldInitializeHttpClientWithCallerAndProxy() {
new UsernamePasswordTokenProvider().getToken(),
new DataAPIClientOptions()
.destination(DataAPIDestination.CASSANDRA)
+ .addObserver(new LoggingCommandObserver(getClass()))
.addCaller("Cedrick", "1.0"));
assertThat(otherCallerClient
.getDatabase(DEFAULT_ENDPOINT_LOCAL)
diff --git a/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_12_Collection_FindAndRerank_ITTest.java b/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_12_Collection_FindAndRerank_ITTest.java
index 0452be9d..974a6567 100644
--- a/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_12_Collection_FindAndRerank_ITTest.java
+++ b/astra-db-java/src/test/java/com/datastax/astra/test/integration/local/Local_12_Collection_FindAndRerank_ITTest.java
@@ -16,7 +16,7 @@
import com.datastax.astra.client.core.query.Projection;
import com.datastax.astra.client.core.query.Sort;
import com.datastax.astra.client.core.rerank.CollectionRerankOptions;
-import com.datastax.astra.client.core.rerank.RerankResult;
+import com.datastax.astra.client.core.rerank.RerankedResult;
import com.datastax.astra.client.core.rerank.RerankServiceOptions;
import com.datastax.astra.client.core.vector.SimilarityMetric;
import com.datastax.astra.client.core.vector.VectorOptions;
@@ -120,6 +120,27 @@ public void should_create_collection_reranking() {
.rerank(rerankOptions);
getDatabase().createCollection("c_find_rerank",def);
+
+
+// getDatabase().createCollection("c_find_rerank", new CollectionDefinition()
+//
+// .vector(new VectorOptions()
+// .dimension(1536)
+// .metric(SimilarityMetric.COSINE.getValue())
+// .service(new VectorServiceOptions()
+// .provider( "openai")
+// .modelName("text-embedding-3-small")))
+//
+// .lexical(new LexicalOptions()
+// .enabled(true)
+// .analyzer(new Analyzer(STANDARD)))
+//
+// .rerank(new CollectionRerankOptions()
+// .enabled(true)
+// .service(new RerankServiceOptions()
+// .modelName("nvidia/llama-3.2-nv-rerankqa-1b-v2")
+// .provider("nvidia"))));
+
}
@Test
@@ -132,6 +153,7 @@ public void should_populate_collection_farr() throws IOException {
// Ingest the CSV
EmbeddingHeadersProvider authEmbedding =
new EmbeddingAPIKeyHeaderProvider(System.getenv("OPENAI_API_KEY"));
+
List docs = Files.readAllLines(Paths.get("src/test/resources/philosopher-quotes.csv"))
.stream().map(line -> {
String[] chunks = line.split(",");
@@ -205,7 +227,7 @@ public void should_query_collection_byov() {
.hybridLimits(20);
// Run the query
- List> result = myCol.findAndRerank(farrOptions).toList();
+ List> result = myCol.findAndRerank(farrOptions).toList();
Assertions.assertNotNull(result);
Assertions.assertFalse(result.isEmpty());
System.out.println("Result3: " + result.size());
diff --git a/astra-sdk-devops/pom.xml b/astra-sdk-devops/pom.xml
new file mode 100644
index 00000000..f0ea8bb9
--- /dev/null
+++ b/astra-sdk-devops/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+ astra-sdk-devops
+ Devops API Client
+
+
+ com.datastax.astra
+ astra-db-java-parent
+ 2.0.0-PREVIEW3
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+ com.fasterxml.jackson
+ jackson-bom
+ ${jackson.version}
+ provided
+ pom
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
+
+
+
+ Apache-2.0
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+ A business-friendly OSS license
+
+
+
+
\ No newline at end of file
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AbstractApiClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AbstractApiClient.java
new file mode 100644
index 00000000..f4268b6d
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AbstractApiClient.java
@@ -0,0 +1,213 @@
+package com.dtsx.astra.sdk;
+
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.HttpClientWrapper;
+import com.dtsx.astra.sdk.utils.observability.ApiRequestObserver;
+import lombok.Getter;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static java.net.HttpURLConnection.HTTP_ACCEPTED;
+
+/**
+ * Super Class for the different Http Clients of the api
+ */
+@Getter
+public abstract class AbstractApiClient {
+
+ /**
+ * Token Value
+ */
+ protected final String token;
+
+ /**
+ * Hold a reference to target Astra Environment.
+ */
+ protected final AstraEnvironment environment;
+
+ /**
+ * Observers to notify.
+ */
+ protected final Map observers = new LinkedHashMap<>();
+
+ /**
+ * Default constructor.
+ *
+ * @param env
+ * astra environment
+ * @param token
+ * token value
+ */
+ public AbstractApiClient(String token, AstraEnvironment env) {
+ Assert.hasLength(token, "token");
+ this.token = token;
+ this.environment = env;
+ }
+
+ /**
+ * Default constructor.
+ *
+ * @param env
+ * astra environment
+ * @param token
+ * token value
+ * @param observers
+ * list of observers
+ */
+ public AbstractApiClient(String token, AstraEnvironment env, Map observers) {
+ Assert.hasLength(token, "token");
+ this.token = token;
+ this.environment = env;
+ this.observers.putAll(observers);
+ }
+
+ /**
+ * Access Http Client.
+ *
+ * @param operation
+ * operation name (tracking)
+ * @return
+ * Http client
+ */
+ public HttpClientWrapper getHttpClient(String operation) {
+ return HttpClientWrapper.getInstance(operation);
+ }
+
+ /**
+ * Provide a service Name.
+ *
+ * @return
+ * service name
+ */
+ public abstract String getServiceName();
+
+ /**
+ * Get the full name for the operation.
+ *
+ * @param operation
+ * operation name
+ * @return
+ * full operation name
+ */
+ protected String getOperationName(String operation) {
+ return getServiceName() + "." + operation;
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param operation
+ * operation name (tracking)
+ * @return
+ * response
+ */
+ public ApiResponseHttp GET(String url, String operation) {
+ return getHttpClient(operation).GET(url, getToken());
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param operation
+ * operation name (tracking)
+ * @return
+ * response
+ */
+ public ApiResponseHttp HEAD(String url, String operation) {
+ return getHttpClient(operation).HEAD(url, getToken());
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param operation
+ * operation name (tracking)
+ * @return
+ * response
+ */
+ public ApiResponseHttp POST(String url, String operation) {
+ return getHttpClient(operation).POST(url, getToken());
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param body
+ * body
+ * @param url
+ * url
+ * @param operation
+ * operation name (tracking)
+ * @return
+ * response
+ */
+ public ApiResponseHttp POST(String url, String body, String operation) {
+ return getHttpClient(operation).POST(url, getToken(), body);
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param body
+ * body
+ * @param operation
+ * operation name (tracking)
+ */
+ public void PUT(String url, String body, String operation) {
+ getHttpClient(operation).PUT(url, getToken(), body);
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param body
+ * body
+ * @param operation
+ * operation name (tracking)
+ */
+ public void PATCH(String url, String body, String operation) {
+ getHttpClient(operation).PATCH(url, getToken(), body);
+ }
+
+ /**
+ * Syntax sugar http requests.
+ *
+ * @param url
+ * url
+ * @param operation
+ * operation name (tracking)
+ */
+ public void DELETE(String url, String operation) {
+ getHttpClient(operation).DELETE(url, getToken());
+ }
+
+ /**
+ * Response validation
+ *
+ * @param res
+ * current response
+ * @param action
+ * action taken
+ * @param entityId
+ * entity id
+ */
+ public void assertHttpCodeAccepted(ApiResponseHttp res, String action, String entityId) {
+ String errorMsg = " Cannot " + action + " id=" + entityId + " code=" + res.getCode() + " msg=" + res.getBody();
+ Assert.isTrue(HTTP_ACCEPTED == res.getCode(), errorMsg);
+ }
+
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AstraOpsClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AstraOpsClient.java
new file mode 100644
index 00000000..8779c630
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/AstraOpsClient.java
@@ -0,0 +1,169 @@
+package com.dtsx.astra.sdk;
+
+import com.dtsx.astra.sdk.db.AstraDBOpsClient;
+import com.dtsx.astra.sdk.org.KeysClient;
+import com.dtsx.astra.sdk.org.RolesClient;
+import com.dtsx.astra.sdk.org.TokensClient;
+import com.dtsx.astra.sdk.org.UsersClient;
+import com.dtsx.astra.sdk.org.domain.*;
+import com.dtsx.astra.sdk.streaming.AstraStreamingClient;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+
+import java.util.Map;
+
+/**
+ * Main Class to interact with Astra Devops API.
+ *
+ *
This class uses
+ */
+public class AstraOpsClient extends AbstractApiClient {
+
+ /**
+ * Initialize the Devops API with a token
+ *
+ * @param token
+ * bearerAuthToken token
+ */
+ public AstraOpsClient(String token) {
+ this(token, AstraEnvironment.PROD);
+ }
+
+ /**
+ * Initialize the Devops API with a token
+ *
+ * @param env
+ * environment Astra
+ * @param token
+ * bearerAuthToken token
+ */
+ public AstraOpsClient(String token, AstraEnvironment env) {
+ super(token, env);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "ops";
+ }
+
+ // ------------------------------------------------------
+ // CORE FEATURES
+ // ------------------------------------------------------
+
+ /**
+ * Retrieve Organization id.
+ *
+ * @return
+ * organization id.
+ */
+ public String getOrganizationId() {
+ // Invoke endpoint
+ ApiResponseHttp res = GET(ApiLocator.getApiDevopsEndpoint(environment) + "/currentOrg", getOperationName("orgId"));
+ // Parse response
+ return (String) JsonUtils.unmarshallBean(res.getBody(), Map.class).get("id");
+ }
+
+ /**
+ * Retrieve the organization wth current token.
+ *
+ * @return
+ * current organization
+ */
+ public Organization getOrganization() {
+ // Invoke endpoint
+ ApiResponseHttp res = GET(users().getEndpointUsers(), getOperationName("org"));
+ // Marshalling the users response to get org infos
+ ResponseAllUsers body = JsonUtils.unmarshallBean(res.getBody(), ResponseAllUsers.class);
+ // Build a proper result
+ return new Organization(body.getOrgId(), body.getOrgName());
+ }
+
+ // ------------------------------------------------------
+ // WORKING WITH ASTRA DB
+ // ------------------------------------------------------
+
+ /**
+ * Works with db.
+ *
+ * @return
+ * databases client
+ */
+ public AstraDBOpsClient db() {
+ return new AstraDBOpsClient(token, environment);
+ }
+
+ // ------------------------------------------------------
+ // WORKING WITH ASTRA STREAMING
+ // ------------------------------------------------------
+
+ /**
+ * Works with Streaming.
+ *
+ * @return
+ * streaming client
+ */
+ public AstraStreamingClient streaming() {
+ return new AstraStreamingClient(token, environment);
+ }
+
+
+ // ------------------------------------------------------
+ // WORKING WITH USERS
+ // ------------------------------------------------------
+
+ /**
+ * List Users.
+ *
+ * @return
+ * user client
+ */
+ public UsersClient users() {
+ return new UsersClient(token, environment);
+ }
+
+ // ------------------------------------------------------
+ // WORKING WITH ROLES
+ // ------------------------------------------------------
+
+ /**
+ * List Roles.
+ *
+ * @return
+ * role client
+ */
+ public RolesClient roles() {
+ return new RolesClient(token, environment);
+ }
+
+ // ------------------------------------------------------
+ // WORKING WITH KEYS
+ // ------------------------------------------------------
+
+ /**
+ * List keys.
+ *
+ * @return
+ * keys client
+ */
+ public KeysClient keys() {
+ return new KeysClient(token, environment);
+ }
+
+ // ------------------------------------------------------
+ // WORKING WITH TOKENS
+ // ------------------------------------------------------
+
+ /**
+ * List tokens.
+ *
+ * @return
+ * token client
+ */
+ public TokensClient tokens() {
+ return new TokensClient(token, environment);
+ }
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/AstraDBOpsClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/AstraDBOpsClient.java
new file mode 100644
index 00000000..f48df076
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/AstraDBOpsClient.java
@@ -0,0 +1,280 @@
+package com.dtsx.astra.sdk.db;
+
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.*;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.ApiResponse;
+import com.dtsx.astra.sdk.utils.ApiResponseError;
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.HttpClientWrapper;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+import com.dtsx.astra.sdk.utils.observability.ApiRequestObserver;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.dtsx.astra.sdk.db.domain.DatabaseFilter.Include;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+
+import java.net.HttpURLConnection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Devops API Client working with Databases.
+ */
+public class AstraDBOpsClient extends AbstractApiClient {
+
+ /** Load Database responses. */
+ private static final TypeReference> RESPONSE_DATABASES =
+ new TypeReference>(){};
+
+ /** Load Database responses. */
+ private static final TypeReference> RESPONSE_ACCESS_LIST =
+ new TypeReference>(){};
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ */
+ public AstraDBOpsClient(String token) {
+ this(token, AstraEnvironment.PROD);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ */
+ public AstraDBOpsClient(String token, AstraEnvironment env) {
+ super(token, env);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param observers
+ * list of observers
+ */
+ public AstraDBOpsClient(String token, AstraEnvironment env, Map observers) {
+ super(token, env, observers);
+ HttpClientWrapper.registerObservers(observers);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db";
+ }
+
+ // ---------------------------------
+ // ---- REGIONS ----
+ // ---------------------------------
+
+ /**
+ * Access Astra Db region topology.
+ *
+ * @return
+ * work with regions
+ */
+ public DbRegionsClient regions() {
+ return new DbRegionsClient(token, getEnvironment());
+ }
+
+
+ // ---------------------------------
+ // ---- GLOBAL ACCESS LIST ----
+ // ---------------------------------
+
+ /**
+ * Find All Access List.
+ * @return
+ * access list
+ */
+ public Stream findAllAccessLists() {
+ return JsonUtils.unmarshallType(GET(getEndpointAccessLists(), getOperationName("findAllAccessLists"))
+ .getBody(), RESPONSE_ACCESS_LIST).stream();
+ }
+
+ // ---------------------------------
+ // ---- CRUD ----
+ // ---------------------------------
+
+ /**
+ * Returns list of databases with default filter.
+ * (include=non terminated, provider=ALL,limit=25)
+ *
+ * @return
+ * matching db
+ */
+ public Stream findAll() {
+ return search(DatabaseFilter.builder()
+ .include(Include.ALL)
+ .provider(CloudProviderType.ALL)
+ .limit(1000)
+ .build());
+ }
+
+ /**
+ * Default Filter to find databases.
+ *
+ * @return
+ * list of non terminated db
+ */
+ public Stream findAllNonTerminated() {
+ return search(DatabaseFilter.builder().build());
+ }
+
+ /**
+ * Retrieve list of all Databases of the account and filter on name
+ *
+ * @param name
+ * a database name
+ * @return
+ * list of db matching the criteria
+ */
+ public Stream findByName(String name) {
+ Assert.hasLength(name, "Database name");
+ return findAllNonTerminated().filter(db->name.equals(db.getInfo().getName()));
+ }
+
+ /**
+ * Retrieve frist DB from its name.
+ * @param name
+ * name
+ * @return
+ * if the db exists or not
+ */
+ public Optional findFirstByName(String name) {
+ return findByName(name).findFirst();
+ }
+
+ /**
+ * Find a database from its id.
+ *
+ * @param id
+ * a database name
+ * @return
+ * list of db matching the criteria
+ */
+ public Optional findById(String id) {
+ Assert.hasLength(id, "Database identifier");
+ return database(id).find();
+ }
+
+ /**
+ * Find Databases matching the provided filter.
+ * Reference Documentation
+ *
+ * @param filter
+ * filter to search for db
+ * @return
+ * list of db
+ */
+ public Stream search(DatabaseFilter filter) {
+ Assert.notNull(filter, "filter");
+ ApiResponseHttp res = GET(getEndpointDatabases() + filter.urlParams(), getOperationName("search"));
+ try {
+ return JsonUtils.unmarshallType(res.getBody(), RESPONSE_DATABASES).stream();
+ } catch(Exception e) {
+ // Specialization of the exception
+ ApiResponseError responseError = null;
+ try {
+ responseError = JsonUtils.unmarshallBean(res.getBody(), ApiResponseError.class);
+ } catch (Exception ef) {}
+ if (responseError!= null && responseError.getErrors() != null && !responseError.getErrors().isEmpty()) {
+ if (responseError.getErrors().get(0).getId() == 340018) {
+ throw new IllegalArgumentException("You have provided an invalid token, please check", e);
+ }
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Create a database base on some parameters.
+ *
+ * @param dbCreationRequest
+ * creation request with tier and capacity unit
+ * @return
+ * the new instance id.
+ *
+ * Reference Documentation
+ */
+ public String create(DatabaseCreationRequest dbCreationRequest) {
+ Assert.notNull(dbCreationRequest, "Database creation request");
+ ApiResponseHttp res = POST(getEndpointDatabases(), JsonUtils.marshall(dbCreationRequest), getOperationName("create"));
+ if (HttpURLConnection.HTTP_CREATED != res.getCode()) {
+ throw new IllegalStateException("Expected code 201 to create db but got "
+ + res.getCode() + "body=" + res.getBody());
+ }
+ return res.getHeaders().get("location");
+ }
+
+ // ---------------------------------
+ // ---- Utilities ----
+ // ---------------------------------
+
+ /**
+ * Use the database part of the API.
+ *
+ * @param dbId
+ * unique identifier id
+ * @return
+ * client specialized for this db
+ */
+ public DbOpsClient database(String dbId) {
+ Assert.hasLength(dbId, "Database Id should not be null nor empty");
+ return new DbOpsClient(token, environment, dbId);
+ }
+
+ /**
+ * Use the database part of the API from its name.
+ *
+ * @param dbName
+ * name for a database
+ * @return DatabaseClient
+ */
+ public DbOpsClient databaseByName(String dbName) {
+ Assert.hasLength(dbName, "Database Id should not be null nor empty");
+ List dbs = findByName(dbName).collect(Collectors.toList());
+ if (1 == dbs.size()) {
+ return new DbOpsClient(token, environment, dbs.get(0).getId());
+ }
+ throw new IllegalArgumentException("Cannot retrieve database from its name (matching count=" + dbs.size() + ")");
+ }
+
+ /**
+ * Endpoint to access schema for namespace.
+ *
+ * @return
+ * endpoint
+ */
+ public String getEndpointDatabases() {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/databases";
+ }
+
+ /**
+ * Endpoint to access schema for namespace.
+ *
+ * @return
+ * endpoint
+ */
+ public String getEndpointAccessLists() {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/access-lists";
+ }
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbAccessListsClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbAccessListsClient.java
new file mode 100644
index 00000000..4bb1597e
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbAccessListsClient.java
@@ -0,0 +1,148 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.AccessList;
+import com.dtsx.astra.sdk.db.domain.AccessListAddressRequest;
+import com.dtsx.astra.sdk.db.domain.AccessListRequest;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Operations on Access List.
+ */
+public class DbAccessListsClient extends AbstractApiClient {
+
+ /**
+ * unique db identifier.
+ */
+ private final Database db;
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbAccessListsClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbAccessListsClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.db = new DbOpsClient(token, env, databaseId).get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db.access-list";
+ }
+
+ /**
+ * Retrieve the access list for a DB.
+ *
+ * @return
+ * current access list
+ */
+ public AccessList get() {
+ try {
+ return JsonUtils.unmarshallBean(GET(
+ getApiDevopsEndpointAccessListsDb(),
+ getOperationName("get")).getBody(), AccessList.class);
+ } catch(RuntimeException mex) {
+ AccessList ac = new AccessList();
+ ac.setDatabaseId(db.getId());
+ ac.setOrganizationId(db.getOrgId());
+ ac.setAddresses(new ArrayList<>());
+ ac.setConfigurations(new AccessList.Configurations(false));
+ return ac;
+ }
+ }
+
+ /**
+ * Create a new Address for the DB.
+ *
+ * @param newAddressed
+ * address to be added
+ * @see Reference Documentation
+ */
+ public void addAddress(AccessListAddressRequest... newAddressed) {
+ Assert.notNull(newAddressed, "New addresses should not be null");
+ Assert.isTrue(newAddressed.length > 0, "New address should not be empty");
+ POST(getApiDevopsEndpointAccessListsDb(),
+ JsonUtils.marshall(newAddressed),
+ getOperationName("addAddress"));
+ }
+
+ /**
+ * Delete the addresses List.
+ *
+ * @see Reference Documentation
+ */
+ public void delete() {
+ DELETE(getApiDevopsEndpointAccessListsDb(), getOperationName("delete"));
+ }
+
+ /**
+ * Replace the addresses for a DB
+ *
+ * @param addresses
+ * address to be added
+ *
+ * @see Reference Documentation
+ */
+ public void replaceAddresses(AccessListAddressRequest... addresses) {
+ Assert.notNull(addresses, "Addresses should not be null");
+ Assert.isTrue(addresses.length > 0, "Address should not be empty");
+ PUT(getApiDevopsEndpointAccessListsDb(),
+ JsonUtils.marshall(addresses),
+ getOperationName("replaceAddresses"));
+ }
+
+ /**
+ * Replace the addresses for a DB
+ *
+ * @param addresses
+ * address to be updated
+ *
+ * @see Reference Documentation
+ */
+ public void update(AccessListAddressRequest... addresses) {
+ Assert.notNull(addresses, "Addresses should not be null");
+ Assert.isTrue(addresses.length > 0, "Address should not be empty");
+ AccessListRequest alr = new AccessListRequest();
+ alr.setAddresses(Arrays.asList(addresses));
+ alr.setConfigurations(new AccessListRequest.Configurations(true));
+ PATCH(getApiDevopsEndpointAccessListsDb(), JsonUtils.marshall(alr), getOperationName("update"));
+ }
+
+ /**
+ * Endpoint to access schema for namespace.
+ *
+ * @return
+ * endpoint
+ */
+ public String getApiDevopsEndpointAccessListsDb() {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/databases/" + db.getId() + "/access-list";
+ }
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbCdcsClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbCdcsClient.java
new file mode 100644
index 00000000..28cb2ae2
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbCdcsClient.java
@@ -0,0 +1,185 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.db.exception.ChangeDataCaptureNotFoundException;
+import com.dtsx.astra.sdk.db.exception.KeyspaceNotFoundException;
+import com.dtsx.astra.sdk.streaming.AstraStreamingClient;
+import com.dtsx.astra.sdk.streaming.domain.CdcDefinition;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * Group Operation regarding Cdc for a DB
+ */
+public class DbCdcsClient extends AbstractApiClient {
+
+ /**
+ * Load Cdc responses.
+ */
+ private static final TypeReference> TYPE_LIST_CDC =
+ new TypeReference>() {
+ };
+
+ /**
+ * unique db identifier.
+ */
+ private final Database db;
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbCdcsClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db.cdc";
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbCdcsClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.db = new DbOpsClient(token, env, databaseId).get();
+ }
+
+ /**
+ * Access Cdc component for a DB.
+ *
+ * @return list of cdc
+ */
+ public Stream findAll() {
+ ApiResponseHttp res = GET(getEndpointDatabaseCdc(), getOperationName("find"));
+ if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
+ return Stream.of();
+ } else {
+ return JsonUtils.unmarshallType(res.getBody(), TYPE_LIST_CDC).stream();
+ }
+ }
+
+ /**
+ * Find a cdc by its id.
+ *
+ * @param cdcId
+ * identifier
+ * @return cdc definition if exist
+ */
+ public Optional findById(String cdcId) {
+ Assert.hasLength(cdcId, "cdc identifier");
+ return findAll().filter(cdc -> cdc.getConnectorName().equals(cdcId)).findFirst();
+ }
+
+ /**
+ * Find the cdc based on its components.
+ *
+ * @param keyspace
+ * keyspace name
+ * @param table
+ * table name
+ * @param tenant
+ * tenant identifier
+ * @return definition if present
+ */
+ public Optional findByDefinition(String keyspace, String table, String tenant) {
+ Assert.hasLength(keyspace, "keyspace");
+ Assert.hasLength(table, "table");
+ Assert.hasLength(tenant, "tenant");
+ return findAll().filter(cdc -> cdc.getKeyspace().equals(keyspace) && cdc.getDatabaseTable().equals(table) && cdc.getTenant().equals(tenant)).findFirst();
+ }
+
+ /**
+ * Create cdc from definition.
+ *
+ * @param keyspace
+ * keyspace name
+ * @param table
+ * table name
+ * @param tenant
+ * tenant identifier
+ * @param topicPartition
+ * topic partition
+ */
+ public void create(String keyspace, String table, String tenant, int topicPartition) {
+ Assert.hasLength(keyspace, "keyspace");
+ if (!db.getInfo().getKeyspaces().contains(keyspace)) {
+ throw new KeyspaceNotFoundException(db.getId(), keyspace);
+ }
+ new AstraStreamingClient(token, environment)
+ .tenant(tenant).cdc()
+ .create(db.getId(), keyspace, table, topicPartition);
+ }
+
+ /**
+ * Delete cdc from its identifier.
+ *
+ * @param cdcId
+ * cdc identifier
+ */
+ public void delete(String cdcId) {
+ delete(findById(cdcId).orElseThrow(() -> new ChangeDataCaptureNotFoundException(cdcId, db.getId())));
+ }
+
+ /**
+ * Delete cdc from its identifier.
+ *
+ * @param keyspace
+ * keyspace name
+ * @param table
+ * table name
+ * @param tenant
+ * tenant identifier
+ */
+ public void delete(String keyspace, String table, String tenant) {
+ delete(findByDefinition(keyspace, table, tenant)
+ .orElseThrow(() -> new ChangeDataCaptureNotFoundException(keyspace, table, tenant, db.getId())));
+ }
+
+ /**
+ * Delete Cdc from its definition.
+ *
+ * @param cdc
+ * cdc definition
+ */
+ private void delete(CdcDefinition cdc) {
+ new AstraStreamingClient(token, environment)
+ .tenant(cdc.getTenant()).cdc()
+ .delete(db.getId(), cdc.getKeyspace(), cdc.getDatabaseTable());
+ }
+
+ /**
+ * Http Client for Cdc list.
+ *
+ * @return url to invoke CDC
+ */
+ private String getEndpointDatabaseCdc() {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/streaming" + "/astra-cdc/databases/" + db.getId();
+ }
+
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbDatacentersClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbDatacentersClient.java
new file mode 100644
index 00000000..b032a0b8
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbDatacentersClient.java
@@ -0,0 +1,168 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.CloudProviderType;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.db.domain.DatabaseRegionCreationRequest;
+import com.dtsx.astra.sdk.db.domain.Datacenter;
+import com.dtsx.astra.sdk.db.exception.RegionAlreadyExistException;
+import com.dtsx.astra.sdk.db.exception.RegionNotFoundException;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import java.net.HttpURLConnection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * Delegate operation on region/datacenters
+ */
+public class DbDatacentersClient extends AbstractApiClient {
+
+ /**
+ * Returned type.
+ */
+ private static final TypeReference> DATACENTER_LIST =
+ new TypeReference>() {};
+
+ /**
+ * unique db identifier.
+ */
+ private final Database db;
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbDatacentersClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbDatacentersClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.db = new DbOpsClient(token, env, databaseId).get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db.regions";
+ }
+
+ /**
+ * Get Datacenters details for a region
+ *
+ * @return list of datacenters.
+ */
+ public Stream findAll() {
+ ApiResponseHttp res = GET(getEndpointRegions(), getOperationName("find"));
+ if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
+ return Stream.of();
+ } else {
+ return JsonUtils.unmarshallType(res.getBody(), DATACENTER_LIST).stream();
+ }
+ }
+
+ /**
+ * Get a region from its name.
+ *
+ * @param regionName
+ * region name
+ * @return datacenter if exists
+ * i
+ */
+ public Optional findByRegionName(String regionName) {
+ Assert.hasLength(regionName, "regionName");
+ return findAll().filter(dc -> regionName.equals(dc.getRegion())).findFirst();
+ }
+
+ /**
+ * Evaluate if a database exists using the findById method.
+ *
+ * @param regionName
+ * region name
+ * @return
+ * if region exist
+ */
+ public boolean exist(String regionName) {
+ return findByRegionName(regionName).isPresent();
+ }
+
+ /**
+ * Create a Region.
+ *
+ * @param tier
+ * tier for the db
+ * @param cloudProvider
+ * Cloud provider to add a region
+ * @param regionName
+ * name of the region
+ *
+ * https://docs.datastax.com/en/astra/docs/_attachments/devopsv2.html#operation/addDatacenters
+ */
+ public void create(String tier, CloudProviderType cloudProvider, String regionName) {
+ Assert.hasLength(tier, "tier");
+ Assert.notNull(cloudProvider, "cloudProvider");
+ Assert.hasLength(regionName, "regionName");
+ if (findByRegionName(regionName).isPresent()) {
+ throw new RegionAlreadyExistException(db.getId(), regionName);
+ }
+ DatabaseRegionCreationRequest req = new DatabaseRegionCreationRequest(tier, cloudProvider.getCode(), regionName);
+ String body = JsonUtils.marshall(Collections.singletonList(req));
+ ApiResponseHttp res = POST(getEndpointRegions(), body, getOperationName("create"));
+ if (res.getCode() != HttpURLConnection.HTTP_CREATED) {
+ throw new IllegalStateException("Cannot Add Region: " + res.getBody());
+ }
+ }
+
+ /**
+ * Delete a region from its name.
+ *
+ * @param regionName
+ * name of the region
+ *
+ * ...
+ */
+ public void delete(String regionName) {
+ Optional optDc = findByRegionName(regionName);
+ if (!optDc.isPresent()) {
+ throw new RegionNotFoundException(db.getId(), regionName);
+ }
+ // Invoke Http endpoint
+ ApiResponseHttp res = POST(getEndpointRegions() + "/" + optDc.get().getId() + "/terminate",
+ getOperationName("delete"));
+ // Check response code
+ assertHttpCodeAccepted(res, "deleteRegion", db.getId());
+ }
+
+ /**
+ * Endpoint to access datacenters of a db
+ *
+ * @return database endpoint
+ */
+ private String getEndpointRegions() {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/databases/" + db.getId() + "/datacenters";
+ }
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbKeyspacesClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbKeyspacesClient.java
new file mode 100644
index 00000000..fe965623
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbKeyspacesClient.java
@@ -0,0 +1,118 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.db.exception.KeyspaceAlreadyExistException;
+import com.dtsx.astra.sdk.db.exception.KeyspaceNotFoundException;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+
+import java.util.Set;
+
+/**
+ * Delegate Operation to work on Keyspaces
+ */
+public class DbKeyspacesClient extends AbstractApiClient {
+
+ /**
+ * unique db identifier.
+ */
+ private final Database db;
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbKeyspacesClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbKeyspacesClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.db = new DbOpsClient(token, env, databaseId).get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db.keyspaces";
+ }
+
+ /**
+ * Find all keyspace in current DB.
+ *
+ * @return
+ * all keyspace names
+ */
+ public Set findAll() {
+ return db.getInfo().getKeyspaces();
+ }
+
+ /**
+ * Evaluate if a keyspace exists.
+ *
+ * @param keyspace
+ * keyspace identifier
+ * @return
+ * if keyspace exists
+ */
+ public boolean exist(String keyspace) {
+ return findAll().contains(keyspace);
+ }
+
+ /**
+ * Create a new keyspace in a DB.
+ *
+ * @param keyspace
+ * keyspace name to create
+ */
+ public void create(String keyspace) {
+ Assert.hasLength(keyspace, "keyspace");
+ if (db.getInfo().getKeyspaces().contains(keyspace)) {
+ throw new KeyspaceAlreadyExistException(keyspace, db.getInfo().getName());
+ }
+ POST(getEndpointKeyspace(keyspace), getOperationName("create"));
+ }
+
+ /**
+ * Delete a keyspace from db.
+ *
+ * @param keyspace
+ * current keyspace
+ */
+ public void delete(String keyspace) {
+ Assert.hasLength(keyspace, "keyspace");
+ if (!db.getInfo().getKeyspaces().contains(keyspace)) {
+ throw new KeyspaceNotFoundException(db.getInfo().getName(), keyspace);
+ }
+ DELETE(getEndpointKeyspace(keyspace),getOperationName("delete"));
+ }
+
+ /**
+ * Endpoint to access keyspace. (static).
+ *
+ * @param keyspaceName
+ * name of keyspace
+ * @return endpoint
+ */
+ public String getEndpointKeyspace(String keyspaceName) {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/databases/" + db.getId() + "/keyspaces/" + keyspaceName;
+ }
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbOpsClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbOpsClient.java
new file mode 100644
index 00000000..0117ea85
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbOpsClient.java
@@ -0,0 +1,446 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.db.domain.DatabaseStatusType;
+import com.dtsx.astra.sdk.db.domain.Datacenter;
+import com.dtsx.astra.sdk.db.exception.DatabaseNotFoundException;
+import com.dtsx.astra.sdk.db.exception.RegionNotFoundException;
+import com.dtsx.astra.sdk.utils.ApiLocator;
+import com.dtsx.astra.sdk.utils.ApiResponseHttp;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+import com.dtsx.astra.sdk.utils.JsonUtils;
+import com.dtsx.astra.sdk.utils.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.HttpURLConnection;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Devops API Client working with a Database.
+ */
+public class DbOpsClient extends AbstractApiClient {
+
+ /**
+ * Logger for our Client.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(DbOpsClient.class);
+
+ /**
+ * unique db identifier.
+ */
+ private final String databaseId;
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db";
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbOpsClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbOpsClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.databaseId = databaseId;
+ }
+
+ // ---------------------------------
+ // ---- READ ----
+ // ---------------------------------
+
+ /**
+ * Retrieve a DB by its id.
+ *
+ * @return the database if present,
+ */
+ public Optional find() {
+ ApiResponseHttp res = GET(getEndpointDatabase(), getOperationName("find"));
+ if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
+ return Optional.empty();
+ } else {
+ return Optional.of(JsonUtils.unmarshallBean(res.getBody(), Database.class));
+ }
+ }
+
+ /**
+ * Retrieve database or throw error.
+ *
+ * @return current db or error
+ */
+ public Database get() {
+ return find().orElseThrow(() -> new DatabaseNotFoundException(databaseId));
+ }
+
+ /**
+ * Evaluate if a database exists using the findById method.
+ *
+ * @return database existence
+ */
+ public boolean exist() {
+ return find().isPresent();
+ }
+
+ /**
+ * If the app is active.
+ *
+ * @return tells if database is ACTIVE
+ */
+ public boolean isActive() {
+ return DatabaseStatusType.ACTIVE == get().getStatus();
+ }
+
+ // ---------------------------------
+ // ---- SECURE BUNDLE ----
+ // ---------------------------------
+
+ /**
+ * Download SecureBundle for a specific data center.
+ * @return
+ * binary content.
+ */
+ public byte[] downloadDefaultSecureConnectBundle() {
+ return Utils.downloadFile(getDefaultSecureConnectBundleUrl());
+ }
+
+ /**
+ * Download SecureBundle for a specific data center
+ *
+ * @param destination
+ * file to save the secure bundle
+ */
+ public void downloadDefaultSecureConnectBundle(String destination) {
+ // Parameters Validation
+ Assert.hasLength(destination, "destination");
+ // Download binary in target folder
+ Utils.downloadFile(getDefaultSecureConnectBundleUrl(), destination);
+ }
+
+ /**
+ * This utility method retrieve the binary content for the bundle.
+ *
+ * @return
+ * secure connect bundle binary content.
+ */
+ private String getDefaultSecureConnectBundleUrl() {
+ if (!isActive())
+ throw new IllegalStateException("Database '" + databaseId + "' is not available.");
+ // Get list of urls
+ ApiResponseHttp res = POST(getEndpointDatabase() + "/secureBundleURL", getOperationName("downloadSecureBundle"));
+ // Mapping
+ return (String) JsonUtils.unmarshallBean(res.getBody(), Map.class).get("downloadURL");
+ }
+
+ /**
+ * Download SecureBundle for a specific data center.
+ *
+ * @param region
+ * region to download the SCB
+ * @return
+ * binary content.
+ */
+ public byte[] downloadSecureConnectBundle(String region) {
+ Assert.hasLength(region, "region");
+ Database db = get();
+ return downloadSecureConnectBundle(db.getInfo()
+ .getDatacenters()
+ .stream()
+ .filter(d -> region.equalsIgnoreCase(d.getRegion()))
+ .findFirst()
+ .orElseThrow(() -> new RegionNotFoundException(region, databaseId)));
+ }
+
+ /**
+ * Download SecureBundle for a specific data center
+ *
+ * @param destination
+ * file to save the secure bundle
+ * @param region
+ * download for a target region
+ */
+ public void downloadSecureConnectBundle(String region, String destination) {
+ Assert.hasLength(region, "region");
+ Assert.hasLength(destination, "destination");
+ Database db = get();
+ downloadSecureConnectBundle(db.getInfo()
+ .getDatacenters()
+ .stream()
+ .filter(d -> region.equalsIgnoreCase(d.getRegion()))
+ .findFirst()
+ .orElseThrow(() -> new RegionNotFoundException(region, databaseId)), destination);
+ }
+
+ /**
+ * Download SCB for a database and a datacenter in target location.
+ *
+ * @param dc
+ * current region
+ */
+ private byte[] downloadSecureConnectBundle(Datacenter dc) {
+ return Utils.downloadFile(dc.getSecureBundleUrl());
+ }
+
+ /**
+ * Download SCB for a database and a datacenter in target location.
+ *
+ * @param dc
+ * current region
+ * @param destination
+ * target destination
+ */
+ private void downloadSecureConnectBundle(Datacenter dc, String destination) {
+ Assert.hasLength(destination, "destination");
+ if (!new File(destination).exists()) {
+ Utils.downloadFile(dc.getSecureBundleUrl(), destination);
+ LOGGER.info("+ Downloading SCB to : {}", destination);
+ } else {
+ LOGGER.debug("+ SCB already available ({}) ", destination);
+ }
+ }
+
+ /**
+ * Download all SecureBundle.
+ *
+ * @param destination
+ * file to save the secured bundle
+ */
+ public void downloadAllSecureConnectBundles(String destination) {
+ Assert.hasLength(destination, "destination");
+ Assert.isTrue(new File(destination).exists(), "Destination folder");
+ Database db = get();
+ db.getInfo()
+ .getDatacenters()
+ .forEach(dc -> downloadSecureConnectBundle(dc, destination + File.separator + buildScbFileName(db.getId(), dc.getRegion())));
+ }
+
+ /**
+ * Build filename for the secure connect bundle.
+ *
+ * @param dId
+ * databaseId
+ * @param dbRegion
+ * databaseRegion
+ * @return file name for the secure bundled
+ */
+ public String buildScbFileName(String dId, String dbRegion) {
+ return "scb_" + dId + "_" + dbRegion + ".zip";
+ }
+
+ // ---------------------------------
+ // ---- MAINTENANCE ----
+ // ---------------------------------
+
+ /**
+ * Parks a database (classic)
+ */
+ public void park() {
+ // Invoke Http endpoint
+ ApiResponseHttp res = POST(getEndpointDatabase() + "/park", getOperationName("park"));
+ // Check response code
+ assertHttpCodeAccepted(res, "park", databaseId);
+ }
+
+ /**
+ * unpark a database.
+ *
+ * ...
+ */
+ public void resetPassword(String username, String password) {
+ // Parameter validations
+ Assert.hasLength(username, "username");
+ Assert.hasLength(password, "password");
+ // Build body
+ String body = "{" + "\"username\": \"" + username + "\", " + "\"password\": \"" + password + "\" }";
+ // Invoke
+ ApiResponseHttp res = POST(getEndpointDatabase() + "/resetPassword", body, getOperationName("resetPassword"));
+ // Check response code
+ assertHttpCodeAccepted(res, "resetPassword", databaseId);
+ }
+
+ // ---------------------------------
+ // ---- Keyspaces ----
+ // ---------------------------------
+
+ /**
+ * Work with keyspaces.
+
+ * @return
+ * keyspaces client
+ */
+ public DbKeyspacesClient keyspaces() {
+ return new DbKeyspacesClient(token, environment, databaseId);
+ }
+
+ // ---------------------------------
+ // ---- Datacenters ----
+ // ---------------------------------
+
+ /**
+ * Delegate datacenters operation in a dedicated class
+ *
+ * @return cdc client
+ */
+ public DbDatacentersClient datacenters() {
+ return new DbDatacentersClient(token, environment, databaseId);
+ }
+
+ // ---------------------------------
+ // ---- Access List ----
+ // ---------------------------------
+
+ /**
+ * Delegate access lists operation in a dedicated class
+ *
+ * @return access list client
+ */
+ public DbAccessListsClient accessLists() {
+ return new DbAccessListsClient(token, environment, databaseId);
+ }
+
+ // ---------------------------------
+ // ---- CDC ----
+ // ---------------------------------
+
+ /**
+ * Delegate cdc operation in a dedicated class
+ *
+ * @return cdc client
+ */
+ public DbCdcsClient cdc() {
+ return new DbCdcsClient(token, environment, databaseId);
+ }
+
+ // ---------------------------------
+ // ---- Telemetry ----
+ // ---------------------------------
+
+ /**
+ * Delegate Telemetry operation in a dedicated class
+ *
+ * @return telemetry client
+ */
+ public DbTelemetryClient telemetry() {
+ return new DbTelemetryClient(token, environment, databaseId);
+ }
+
+
+ // ---------------------------------
+ // ---- Private Links ----
+ // ---------------------------------
+
+ /**
+ * Delegate privateLink operation in a dedicated class
+ *
+ * @return privateLink client
+ */
+ public DbPrivateLinksClient privateLink() {
+ return new DbPrivateLinksClient(token, environment, databaseId);
+ }
+
+ // ---------------------------------
+ // ---- Utilities ----
+ // ---------------------------------
+
+ /**
+ * Gets databaseId
+ *
+ * @return value of databaseId
+ */
+ public String getDatabaseId() {
+ return databaseId;
+ }
+
+ /**
+ * Endpoint to access dbs.
+ *
+ * @return database endpoint
+ */
+ public String getEndpointDatabase() {
+ return getEndpointDatabase(databaseId);
+ }
+
+ /**
+ * Endpoint to access dbs (static)
+ *
+ * @param dbId
+ * database identifier
+ * @return database endpoint
+ */
+ public String getEndpointDatabase(String dbId) {
+ return ApiLocator.getApiDevopsEndpoint(environment) + "/databases/" + dbId;
+ }
+
+
+}
diff --git a/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbPrivateLinksClient.java b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbPrivateLinksClient.java
new file mode 100644
index 00000000..9a520df0
--- /dev/null
+++ b/astra-sdk-devops/src/main/java/com/dtsx/astra/sdk/db/DbPrivateLinksClient.java
@@ -0,0 +1,144 @@
+package com.dtsx.astra.sdk.db;
+
+import com.dtsx.astra.sdk.AbstractApiClient;
+import com.dtsx.astra.sdk.db.domain.Database;
+import com.dtsx.astra.sdk.utils.Assert;
+import com.dtsx.astra.sdk.utils.AstraEnvironment;
+
+import java.util.Optional;
+
+/**
+ * Delegate private link operations.
+ */
+public class DbPrivateLinksClient extends AbstractApiClient {
+
+ /**
+ * unique db identifier.
+ */
+ private final Database db;
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbPrivateLinksClient(String token, String databaseId) {
+ this(token, AstraEnvironment.PROD, databaseId);
+ }
+
+ /**
+ * As immutable object use builder to initiate the object.
+ *
+ * @param env
+ * define target environment to be used
+ * @param token
+ * authenticated token
+ * @param databaseId
+ * database identifier
+ */
+ public DbPrivateLinksClient(String token, AstraEnvironment env, String databaseId) {
+ super(token, env);
+ Assert.hasLength(databaseId, "databaseId");
+ this.db = new DbOpsClient(token, env, databaseId).get();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getServiceName() {
+ return "db.private-link";
+ }
+
+ /**
+ * TODO Get info about all private endpoint connections for a specific database
+ *
+ * ...
+ */
+ public void findAll() {
+ System.out.println(db);
+ throw new RuntimeException("This function is not yet implemented");
+ }
+
+ /**
+ * TODO Get info about private endpoints in a region.
+ *
+ * @param region
+ * current region where add the private link
+ *
+ * ...
+ */
+ public void findAll(String region) {
+ throw new RuntimeException("This function is not yet implemented");
+ }
+
+ /**
+ * TODO Add an allowed principal to the service.
+ *
+ * @param region
+ * region where add the principal
+ * Configure a private endpoint connection by providing the allowed principal to connect with
+ */
+ public void createPrincipal(String region) {
+ throw new RuntimeException("This function is not yet implemented");
+ }
+
+ /**
+ * TODO Accept a private endpoint connection.
+ *
+ * @param region
+ * region where add the private endpoint
+ *
+ *...
+ */
+ public void create(String region) {
+ throw new RuntimeException("This function is not yet implemented");
+ }
+
+ /**
+ * TODO Get a specific endpoint.
+ *
+ * ...
+ *
+ * @param region
+ * current region
+ * @param endpointId
+ * endpoint id fo the region
+ * @return the private endpoint of exist
+ */
+ public Optional