From 700a624dfba395e7de836925dc336d0df128b011 Mon Sep 17 00:00:00 2001 From: Lucas Pedroza Date: Wed, 6 Nov 2024 16:32:52 +0100 Subject: [PATCH 1/2] Fix checkstyle and javadocs in com.fauna.response --- .../com/fauna/response/ConstraintFailure.java | 285 ++++++++++++------ .../java/com/fauna/response/ErrorInfo.java | 211 +++++++++---- .../response/MultiByteBufferInputStream.java | 26 +- .../java/com/fauna/response/QueryFailure.java | 2 +- .../com/fauna/response/QueryResponse.java | 270 ++++++++++++----- .../java/com/fauna/response/QueryStats.java | 168 +++++------ .../java/com/fauna/response/QuerySuccess.java | 6 +- 7 files changed, 654 insertions(+), 314 deletions(-) diff --git a/src/main/java/com/fauna/response/ConstraintFailure.java b/src/main/java/com/fauna/response/ConstraintFailure.java index 253ae492..04b9b9ba 100644 --- a/src/main/java/com/fauna/response/ConstraintFailure.java +++ b/src/main/java/com/fauna/response/ConstraintFailure.java @@ -9,71 +9,41 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -public class ConstraintFailure { +public final class ConstraintFailure { private final String message; private final String name; private final PathElement[][] paths; - public ConstraintFailure(String message, String name, - PathElement[][] paths) { + /** + * Initialize a new ConstraintFailure instance. + * + * @param message The constraint failure message. + * @param name The constraint failure name. + * @param paths The constraint failure paths. + */ + public ConstraintFailure( + final String message, + final String name, + final PathElement[][] paths) { this.message = message; this.name = name; this.paths = paths; } - public static class PathElement { - private String sVal = null; - private Integer iVal = null; - - public PathElement(String sVal) { - this.sVal = sVal; - } - - public PathElement(Integer iVal) { - this.iVal = iVal; - } - - public boolean isString() { - return sVal != null; - } - - /** - * Note that this parse method does not advance the parser. - * - * @param parser A JsonParser instance. - * @return A new PathElement. - * @throws IOException Can be thrown if e.g. stream ends. - */ - public static PathElement parse(JsonParser parser) throws IOException { - if (parser.currentToken().isNumeric()) { - return new PathElement(parser.getValueAsInt()); - } else { - return new PathElement(parser.getText()); - } - } - - @Override - public boolean equals(Object o) { - if (o instanceof PathElement) { - PathElement other = (PathElement) o; - return other.isString() == this.isString() && - other.toString().equals(this.toString()); - } else { - return false; - } - } - - public String toString() { - return sVal == null ? String.valueOf(iVal) : sVal; - } - } - - public static PathElement[] createPath(Object... elements) { + /** + * Constructs a PathElement[] from the provided objects. Supported types + * are String and Integer. + * + * @param elements The String objects or Integer objects to use. + * @return A array of PathElement instances. + */ + public static PathElement[] createPath(final Object... elements) { List path = new ArrayList<>(); for (Object element : elements) { if (element instanceof String) { @@ -88,41 +58,24 @@ public static PathElement[] createPath(Object... elements) { return path.toArray(new PathElement[0]); } - - public static class Builder { - private String message = null; - private String name = null; - private final List paths = new ArrayList<>(); - - public Builder message(String message) { - this.message = message; - return this; - } - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder path(PathElement[] path) { - this.paths.add(path); - return this; - } - - public ConstraintFailure build() { - PathElement[][] paths = - this.paths.toArray(new PathElement[this.paths.size()][]); - return new ConstraintFailure(this.message, this.name, - this.paths.isEmpty() ? null : paths); - } - - } - + /** + * Initializes a new empty Builder. + * + * @return A new Builder + */ public static Builder builder() { return new Builder(); } - public static ConstraintFailure parse(JsonParser parser) + /** + * Builds a ConstraintFailure instance from the provided JsonParser. + * + * @param parser The JsonParser to consume. + * @return A new ConstraintFailure instance. + * @throws IOException Thrown if an error is encountered while reading the + * parser. + */ + public static ConstraintFailure parse(final JsonParser parser) throws IOException { if (parser.currentToken() != JsonToken.START_OBJECT && parser.nextToken() != JsonToken.START_OBJECT) { @@ -152,8 +105,8 @@ public static ConstraintFailure parse(JsonParser parser) } } else if (firstPathToken != JsonToken.VALUE_NULL) { throw new ClientResponseException( - "Constraint failure path should be array or null, got: " + - firstPathToken.toString()); + "Constraint failure path should be array or null, got: " + + firstPathToken.toString()); } paths.forEach(builder::path); break; @@ -163,18 +116,38 @@ public static ConstraintFailure parse(JsonParser parser) } + /** + * Gets the constraint failure message. + * + * @return A string representation of the message. + */ public String getMessage() { return this.message; } + /** + * Gets the constraint failure name. + * + * @return A string representation of the name. + */ public Optional getName() { return Optional.ofNullable(this.name); } + /** + * Gets an optional of path elements related to the constraint failure. + * + * @return An array of arrays of PathElements. + */ public Optional getPaths() { return Optional.ofNullable(paths); } + /** + * Gets a list of string representations of the constraint failure paths. + * + * @return A list of string representations of constraint failure paths. + */ public Optional> getPathStrings() { if (paths == null) { return Optional.empty(); @@ -187,7 +160,13 @@ public Optional> getPathStrings() { } } - public boolean pathsAreEqual(ConstraintFailure otherFailure) { + /** + * Tests path equality with another ConstraintFailure. + * + * @param otherFailure The other ConstraintFailure. + * @return True if the paths are equal. + */ + public boolean pathsAreEqual(final ConstraintFailure otherFailure) { PathElement[][] thisArray = this.getPaths().orElse(new PathElement[0][]); PathElement[][] otherArray = @@ -195,7 +174,8 @@ public boolean pathsAreEqual(ConstraintFailure otherFailure) { return Arrays.deepEquals(thisArray, otherArray); } - public boolean equals(Object other) { + @Override + public boolean equals(final Object other) { if (other instanceof ConstraintFailure) { ConstraintFailure otherFailure = (ConstraintFailure) other; return this.getMessage().equals(otherFailure.getMessage()) @@ -206,4 +186,137 @@ public boolean equals(Object other) { } } + @Override + public int hashCode() { + return Objects.hash( + this.name, + this.message, + Arrays.deepHashCode(this.paths)); + } + + public static final class PathElement { + private String sVal = null; + private Integer iVal = null; + + /** + * Initializes a PathElement with a string value. + * + * @param sVal The string value. + */ + public PathElement(final String sVal) { + this.sVal = sVal; + } + + /** + * Initializes a PathElement with an integer value. + * + * @param iVal The integer value. + */ + public PathElement(final Integer iVal) { + this.iVal = iVal; + } + + /** + * Note that this parse method does not advance the parser. + * + * @param parser A JsonParser instance. + * @return A new PathElement. + * @throws IOException Can be thrown if e.g. stream ends. + */ + public static PathElement parse(final JsonParser parser) + throws IOException { + if (parser.currentToken().isNumeric()) { + return new PathElement(parser.getValueAsInt()); + } else { + return new PathElement(parser.getText()); + } + } + + /** + * Tests whether the PathElement stores a string or an integer. + * + * @return True if it's a string, else false. + */ + public boolean isString() { + return sVal != null; + } + + @Override + public boolean equals(final Object o) { + if (o instanceof PathElement) { + PathElement other = (PathElement) o; + return other.isString() == this.isString() && + other.toString().equals(this.toString()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + /** + * Converts the PathElement to a string. + * + * @return A string representation of the PathElement. + */ + public String toString() { + return sVal == null ? String.valueOf(iVal) : sVal; + } + } + + public static class Builder { + private final List paths = new ArrayList<>(); + private String message = null; + private String name = null; + + /** + * Sets a message on the builder. + * + * @param message The message to set. + * @return this + */ + public Builder message(final String message) { + this.message = message; + return this; + } + + /** + * Sets a name on the builder. + * + * @param name The name to set. + * @return this + */ + public Builder name(final String name) { + this.name = name; + return this; + } + + /** + * Sets a path on the builder. + * + * @param path The path to set. + * @return this. + */ + public Builder path(final PathElement[] path) { + this.paths.add(path); + return this; + } + + /** + * Builds a ConstraintFailure instance from the current builder. + * + * @return A ConstraintFailure instance. + */ + public ConstraintFailure build() { + PathElement[][] paths = + this.paths.toArray(new PathElement[this.paths.size()][]); + return new ConstraintFailure(this.message, this.name, + this.paths.isEmpty() ? null : paths); + } + + } + } diff --git a/src/main/java/com/fauna/response/ErrorInfo.java b/src/main/java/com/fauna/response/ErrorInfo.java index fb22ce61..7883a29e 100644 --- a/src/main/java/com/fauna/response/ErrorInfo.java +++ b/src/main/java/com/fauna/response/ErrorInfo.java @@ -29,31 +29,135 @@ public class ErrorInfo { private final ConstraintFailure[] constraintFailures; private final TreeNode abort; - public ErrorInfo(String code, String message, - ConstraintFailure[] constraintFailures, TreeNode abort) { + /** + * Initializes a new ErrorInfo. + * + * @param code The Fauna error code + * @param message The error message + * @param constraintFailures The constraint failures, if any + * @param abort A abort JSON node of the response, if any + */ + public ErrorInfo( + final String code, + final String message, + final ConstraintFailure[] constraintFailures, + final TreeNode abort) { this.code = code; this.message = message; this.constraintFailures = constraintFailures; this.abort = abort; } + /** + * A utility method to instantiate an empty builder. + * + * @return A new builder + */ + public static Builder builder() { + return new Builder(); + } + + private static Builder handleField(final Builder builder, + final JsonParser parser) + throws IOException { + String fieldName = parser.getCurrentName(); + switch (fieldName) { + case ERROR_CODE_FIELD_NAME: + return builder.code(parser.nextTextValue()); + case ERROR_MESSAGE_FIELD_NAME: + return builder.message(parser.nextTextValue()); + case ERROR_ABORT_FIELD_NAME: + parser.nextToken(); + return builder.abort(new ObjectMapper().readTree(parser)); + case ERROR_CONSTRAINT_FAILURES_FIELD_NAME: + List failures = new ArrayList<>(); + JsonToken token = parser.nextToken(); + if (token == JsonToken.VALUE_NULL) { + return builder; + } else if (token == JsonToken.START_ARRAY) { + JsonToken nextToken = parser.nextToken(); + while (nextToken == JsonToken.START_OBJECT) { + failures.add(ConstraintFailure.parse(parser)); + nextToken = parser.nextToken(); + } + return builder.constraintFailures(failures); + } else { + throw new ClientResponseException( + "Unexpected token in constraint failures: " + + token); + } + default: + throw new ClientResponseException( + "Unexpected token in error info: " + + parser.currentToken()); + } + } + + /** + * Builds a new ErrorInfo from a JsonParser. + * + * @param parser The JsonParser to read. + * @return A new ErrorInfo instance. + * @throws IOException Thrown on errors reading from the parser. + */ + public static ErrorInfo parse(final JsonParser parser) throws IOException { + if (parser.nextToken() != JsonToken.START_OBJECT) { + throw new ClientResponseException( + "Error parsing error info, got token" + + parser.currentToken()); + } + Builder builder = ErrorInfo.builder(); + + while (parser.nextToken() == JsonToken.FIELD_NAME) { + builder = handleField(builder, parser); + } + return builder.build(); + } + + /** + * Gets the Fauna error code. + * + * @return A string representing the Fauna error code. + */ public String getCode() { return code; } + /** + * Gets the error message. + * + * @return A string representing the error message. + */ public String getMessage() { return message; } + /** + * Gets the constraint failures. + * + * @return An optional containing the constraint failures. + */ public Optional getConstraintFailures() { return Optional.ofNullable(this.constraintFailures); } + /** + * Gets the abort JSON node. + * + * @return An optional TreeNode with the abort data. + */ public Optional getAbortJson() { return Optional.ofNullable(this.abort); } - public Optional getAbort(Class abortDataClass) { + /** + * Parses the abort data into the provided class. + * + * @param abortDataClass The class to decode into. + * @param The type to decode into. + * @return An instance of the provided type. + */ + public Optional getAbort(final Class abortDataClass) { return this.getAbortJson().map(tree -> { UTF8FaunaParser parser = new UTF8FaunaParser(tree.traverse()); Codec codec = DefaultCodecProvider.SINGLETON.get(abortDataClass); @@ -62,91 +166,66 @@ public Optional getAbort(Class abortDataClass) { }); } - public static class Builder { - String code = null; - String message = null; - ConstraintFailure[] constraintFailures = null; - TreeNode abort = null; - - public Builder code(String code) { + private String code = null; + private String message = null; + private ConstraintFailure[] constraintFailures = null; + private TreeNode abort = null; + + /** + * Sets the error code on the builder. + * + * @param code The error code. + * @return this + */ + public Builder code(final String code) { this.code = code; return this; } - public Builder message(String message) { + /** + * Sets the message on the builder. + * + * @param message The message. + * @return this + */ + public Builder message(final String message) { this.message = message; return this; } - public Builder abort(TreeNode abort) { + /** + * Sets the abort data on the builder. + * + * @param abort The abort JSON node. + * @return this + */ + public Builder abort(final TreeNode abort) { this.abort = abort; return this; } + /** + * Sets the constraint failures on the builder. + * + * @param constraintFailures The constraint failures. + * @return this + */ public Builder constraintFailures( - List constraintFailures) { + final List constraintFailures) { this.constraintFailures = constraintFailures.toArray(new ConstraintFailure[0]); return this; } + /** + * Returns a new ErrorInfo instance based on the current builder. + * + * @return An ErrorInfo instance + */ public ErrorInfo build() { return new ErrorInfo(this.code, this.message, this.constraintFailures, this.abort); } } - - public static Builder builder() { - return new Builder(); - } - - private static Builder handleField(Builder builder, JsonParser parser) - throws IOException { - String fieldName = parser.getCurrentName(); - switch (fieldName) { - case ERROR_CODE_FIELD_NAME: - return builder.code(parser.nextTextValue()); - case ERROR_MESSAGE_FIELD_NAME: - return builder.message(parser.nextTextValue()); - case ERROR_ABORT_FIELD_NAME: - parser.nextToken(); - return builder.abort(new ObjectMapper().readTree(parser)); - case ERROR_CONSTRAINT_FAILURES_FIELD_NAME: - List failures = new ArrayList<>(); - JsonToken token = parser.nextToken(); - if (token == JsonToken.VALUE_NULL) { - return builder; - } else if (token == JsonToken.START_ARRAY) { - JsonToken nextToken = parser.nextToken(); - while (nextToken == JsonToken.START_OBJECT) { - failures.add(ConstraintFailure.parse(parser)); - nextToken = parser.nextToken(); - } - return builder.constraintFailures(failures); - } else { - throw new ClientResponseException( - "Unexpected token in constraint failures: " + - token); - } - default: - throw new ClientResponseException( - "Unexpected token in error info: " + - parser.currentToken()); - } - } - - public static ErrorInfo parse(JsonParser parser) throws IOException { - if (parser.nextToken() != JsonToken.START_OBJECT) { - throw new ClientResponseException( - "Error parsing error info, got token" + - parser.currentToken()); - } - Builder builder = ErrorInfo.builder(); - - while (parser.nextToken() == JsonToken.FIELD_NAME) { - builder = handleField(builder, parser); - } - return builder.build(); - } } diff --git a/src/main/java/com/fauna/response/MultiByteBufferInputStream.java b/src/main/java/com/fauna/response/MultiByteBufferInputStream.java index 017cc8e8..4051e063 100644 --- a/src/main/java/com/fauna/response/MultiByteBufferInputStream.java +++ b/src/main/java/com/fauna/response/MultiByteBufferInputStream.java @@ -13,21 +13,38 @@ * although markSupported() returns false for this class. */ public class MultiByteBufferInputStream extends InputStream { - + private final int ff = 0xFF; private final List buffers; private int index = 0; private ByteBuffer currentBuffer; - public MultiByteBufferInputStream(List initialBuffers) { + /** + * Initializes a MultiByteBufferInputStream using the provided byte buffers. + * + * @param initialBuffers A list of ByteBuffers to use. + */ + public MultiByteBufferInputStream(final List initialBuffers) { this.buffers = initialBuffers; this.currentBuffer = buffers.get(index); } - public synchronized void add(List additionalBuffers) { + /** + * Adds additional byte buffers to this instance in a thread-safe manner. + * + * @param additionalBuffers The additional ByteBuffers. + */ + public synchronized void add(final List additionalBuffers) { buffers.addAll(additionalBuffers); } + /** + * Reads the next byte from the buffer. + * + * @return The next byte. + * @throws IOException Thrown when the byte buffers are exhausted. + */ + @SuppressWarnings("checkstyle:MagicNumber") @Override public synchronized int read() throws IOException { if (currentBuffer.hasRemaining()) { @@ -41,6 +58,9 @@ public synchronized int read() throws IOException { } } + /** + * Resets the byte buffer. + */ @Override public synchronized void reset() { for (ByteBuffer buffer : buffers.subList(0, index)) { diff --git a/src/main/java/com/fauna/response/QueryFailure.java b/src/main/java/com/fauna/response/QueryFailure.java index 2c2df354..c1c164fa 100644 --- a/src/main/java/com/fauna/response/QueryFailure.java +++ b/src/main/java/com/fauna/response/QueryFailure.java @@ -10,7 +10,7 @@ public final class QueryFailure extends QueryResponse { public QueryFailure(int httpStatus, Builder builder) { super(builder); this.statusCode = httpStatus; - this.errorInfo = builder.error; + this.errorInfo = builder.getError(); } public int getStatusCode() { diff --git a/src/main/java/com/fauna/response/QueryResponse.java b/src/main/java/com/fauna/response/QueryResponse.java index e765339b..4b88dac7 100644 --- a/src/main/java/com/fauna/response/QueryResponse.java +++ b/src/main/java/com/fauna/response/QueryResponse.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.http.HttpResponse; import java.util.Map; @@ -37,7 +38,7 @@ public abstract class QueryResponse { private final QueryStats stats; @SuppressWarnings("rawtypes") - QueryResponse(Builder builder) { + QueryResponse(final Builder builder) { this.lastSeenTxn = builder.lastSeenTxn; this.summary = builder.summary; this.schemaVersion = builder.schemaVersion; @@ -45,75 +46,19 @@ public abstract class QueryResponse { this.queryTags = builder.queryTags; } - public static class Builder { - final Codec codec; - Long lastSeenTxn; - String summary; - Long schemaVersion; - QueryStats stats; - QueryTags queryTags; - String staticType; - ErrorInfo error; - T data; - - public Builder(Codec codec) { - this.codec = codec; - } - - public Builder lastSeenTxn(Long lastSeenTxn) { - this.lastSeenTxn = lastSeenTxn; - return this; - } - - public Builder schemaVersion(Long schemaVersion) { - this.schemaVersion = schemaVersion; - return this; - } - - public Builder data(JsonParser parser) { - UTF8FaunaParser faunaParser = new UTF8FaunaParser(parser); - faunaParser.read(); - this.data = this.codec.decode(faunaParser); - return this; - } - - public Builder queryTags(QueryTags tags) { - this.queryTags = tags; - return this; - } - - public Builder error(ErrorInfo info) { - this.error = info; - return this; - } - - public Builder staticType(String staticType) { - this.staticType = staticType; - return this; - } - - public Builder summary(String summary) { - this.summary = summary; - return this; - } - - public Builder stats(QueryStats stats) { - this.stats = stats; - return this; - } - - public QuerySuccess buildSuccess() { - return new QuerySuccess<>(this); - } - - } - - public static Builder builder(Codec codec) { + /** + * A helper method to instantiate a new builder. + * + * @param codec The codec to use when parsing data. + * @param The return type of the data. + * @return A new Builder instance. + */ + public static Builder builder(final Codec codec) { return new Builder<>(codec); } - private static Builder handleField(Builder builder, - JsonParser parser) + private static Builder handleField(final Builder builder, + final JsonParser parser) throws IOException { String fieldName = parser.getCurrentName(); switch (fieldName) { @@ -139,9 +84,20 @@ private static Builder handleField(Builder builder, } } + /** + * A helper method to adapt an HTTP response into a QuerySuccess or throw + * the appropriate FaunaException. + * + * @param response The HTTP response to adapt. + * @param codec The codec to use when reading the HTTP response body. + * @param statsCollector The stats collector to accumulate stats against. + * @param The response type on success. + * @return A QuerySuccess instance. + * @throws FaunaException Thrown on non-200 responses. + */ public static QuerySuccess parseResponse( - HttpResponse response, Codec codec, - StatsCollector statsCollector) throws FaunaException { + final HttpResponse response, final Codec codec, + final StatsCollector statsCollector) throws FaunaException { try { JsonParser parser = JSON_FACTORY.createParser(response.body()); @@ -160,7 +116,7 @@ public static QuerySuccess parseResponse( } int httpStatus = response.statusCode(); - if (httpStatus >= 400) { + if (httpStatus >= HttpURLConnection.HTTP_BAD_REQUEST) { QueryFailure failure = new QueryFailure(httpStatus, builder); ErrorHandler.handleQueryFailure(response.statusCode(), failure); // Fall back on ProtocolException. @@ -175,25 +131,197 @@ public static QuerySuccess parseResponse( } - + /** + * Gets the last seen transaction timestamp. + * + * @return A long representing the last seen transaction timestamp. + */ public Long getLastSeenTxn() { return lastSeenTxn; } + /** + * Gets the schema version. + * + * @return A long representing the schema version. + */ public Long getSchemaVersion() { return schemaVersion; } + /** + * Gets the summary associated with the response. + * + * @return A string representing the summary. + */ public String getSummary() { return summary; } + /** + * Gets the query tags associated with the response. + * + * @return A Map containing the query tags. + */ public Map getQueryTags() { return queryTags; } + /** + * Gets the query stats associated with the response. + * + * @return A QueryStats instance. + */ public QueryStats getStats() { return stats; } + + public static final class Builder { + private final Codec codec; + private Long lastSeenTxn; + private String summary; + private Long schemaVersion; + private QueryStats stats; + private QueryTags queryTags; + private String staticType; + private ErrorInfo error; + private T data; + + /** + * Initializes a QueryResponse.Builder. + * + * @param codec The codec to use when building data. + */ + public Builder(final Codec codec) { + this.codec = codec; + } + + /** + * Set the last seen transaction timestamp on the builder. + * + * @param lastSeenTxn The last seen transaction timestamp. + * @return This + */ + public Builder lastSeenTxn(final Long lastSeenTxn) { + this.lastSeenTxn = lastSeenTxn; + return this; + } + + /** + * Set the schema version on the builder. + * + * @param schemaVersion The schema version. + * @return This + */ + public Builder schemaVersion(final Long schemaVersion) { + this.schemaVersion = schemaVersion; + return this; + } + + /** + * Set the data on the builder by consuming the provided JsonParser with + * the configured codec. + * + * @param parser The JsonParser to consume. + * @return This + */ + public Builder data(final JsonParser parser) { + UTF8FaunaParser faunaParser = new UTF8FaunaParser(parser); + faunaParser.read(); + this.data = this.codec.decode(faunaParser); + return this; + } + + /** + * Set the query tags on the builder. + * + * @param tags The query tags to set. + * @return This + */ + public Builder queryTags(final QueryTags tags) { + this.queryTags = tags; + return this; + } + + /** + * Sets the error info on the builder. + * + * @param info The error info to set. + * @return This + */ + public Builder error(final ErrorInfo info) { + this.error = info; + return this; + } + + /** + * Sets the static type on the builder. + * + * @param staticType The static type to set. + * @return This + */ + public Builder staticType(final String staticType) { + this.staticType = staticType; + return this; + } + + /** + * Sets the summary on the builder. + * + * @param summary The summary to set. + * @return This + */ + public Builder summary(final String summary) { + this.summary = summary; + return this; + } + + /** + * Sets the query stats on the builder. + * + * @param stats The query stats to set. + * @return This + */ + public Builder stats(final QueryStats stats) { + this.stats = stats; + return this; + } + + /** + * Builds a QuerySuccess. + * + * @return A QuerySuccess from the current builder. + */ + public QuerySuccess buildSuccess() { + return new QuerySuccess<>(this); + } + + /** + * Gets a string representing the static type. + * + * @return A string representing the static type. + */ + public String getStaticType() { + return staticType; + } + + /** + * Gets an ErrorInfo instance representing an error on the response. + * + * @return An ErrorInfo instance. + */ + public ErrorInfo getError() { + return error; + } + + /** + * Gets the parsed data from the response. + * + * @return The parsed data. + */ + public T getData() { + return data; + } + } } diff --git a/src/main/java/com/fauna/response/QueryStats.java b/src/main/java/com/fauna/response/QueryStats.java index 7f8159ea..67cdcea6 100644 --- a/src/main/java/com/fauna/response/QueryStats.java +++ b/src/main/java/com/fauna/response/QueryStats.java @@ -45,7 +45,7 @@ public final class QueryStats { * requests. * @param rateLimitsHit Operation types that exceeded * plan - * throughput limits. + * throughput limits. */ public QueryStats(final int computeOps, final int readOps, final int writeOps, @@ -64,6 +64,71 @@ public QueryStats(final int computeOps, final int readOps, this.rateLimitsHit = rateLimitsHit != null ? rateLimitsHit : List.of(); } + static Builder builder() { + return new Builder(); + } + + static Builder parseField(final Builder builder, final JsonParser parser) + throws IOException { + String fieldName = parser.getValueAsString(); + switch (fieldName) { + case ResponseFields.STATS_COMPUTE_OPS_FIELD_NAME: + return builder.computeOps(parser.nextIntValue(0)); + case ResponseFields.STATS_READ_OPS: + return builder.readOps(parser.nextIntValue(0)); + case ResponseFields.STATS_WRITE_OPS: + return builder.writeOps(parser.nextIntValue(0)); + case ResponseFields.STATS_QUERY_TIME_MS: + return builder.queryTimeMs(parser.nextIntValue(0)); + case ResponseFields.STATS_PROCESSING_TIME_MS: + return builder.processingTimeMs(parser.nextIntValue(0)); + case ResponseFields.STATS_CONTENTION_RETRIES: + return builder.contentionRetries(parser.nextIntValue(0)); + case ResponseFields.STATS_STORAGE_BYTES_READ: + return builder.storageBytesRead(parser.nextIntValue(0)); + case ResponseFields.STATS_STORAGE_BYTES_WRITE: + return builder.storageBytesWrite(parser.nextIntValue(0)); + case ResponseFields.STATS_RATE_LIMITS_HIT: + List limits = new ArrayList<>(); + if (parser.nextToken() == START_ARRAY) { + while (parser.nextToken() == VALUE_STRING) { + limits.add(parser.getValueAsString()); + } + } + return builder.rateLimitsHit(limits); + default: + throw new ClientResponseException("Unknown field " + fieldName); + } + } + + /** + * Parse QueryStats from a JsonParser. + * + * @param parser the JsonParser to consume + * @return a QueryStats object containing the parsed stats + * @throws IOException thrown from the JsonParser + */ + public static QueryStats parseStats(final JsonParser parser) + throws IOException { + if (parser.nextToken() == START_OBJECT) { + Builder builder = builder(); + while (parser.nextToken() == FIELD_NAME) { + builder = parseField(builder, parser); + } + return builder.build(); + } else if (parser.nextToken() == VALUE_NULL) { + return null; + } else { + throw new ClientResponseException( + "Query stats should be an object or null, not " + + parser.getCurrentToken()); + } + } + + private static String statString(final String name, final Object value) { + return String.join(": ", name, String.valueOf(value)); + } + /** * Gets the Transactional Compute Operations (TCOs) recorded. * @@ -140,7 +205,7 @@ public int getStorageBytesWrite() { /** * Gets a list of operation types that exceeded their plan - * throughput limits. + * throughput limits. * * @return A list of operation types that exceeded their throughput limit. */ @@ -148,6 +213,23 @@ public List getRateLimitsHit() { return rateLimitsHit; } + @Override + public String toString() { + if (this.stringValue == null) { + this.stringValue = String.join(", ", + statString("compute", computeOps), + statString("read", readOps), + statString("write", writeOps), + statString("queryTime", queryTimeMs), + statString("retries", contentionRetries), + statString("storageRead", storageBytesRead), + statString("storageWrite", storageBytesWrite), + statString("limits", rateLimitsHit) + ); + } + return this.stringValue; + } + static class Builder { private int computeOps; private int readOps; @@ -210,86 +292,4 @@ QueryStats build() { processingTimeMs, rateLimitsHit); } } - - static Builder builder() { - return new Builder(); - } - - static Builder parseField(final Builder builder, final JsonParser parser) - throws IOException { - String fieldName = parser.getValueAsString(); - switch (fieldName) { - case ResponseFields.STATS_COMPUTE_OPS_FIELD_NAME: - return builder.computeOps(parser.nextIntValue(0)); - case ResponseFields.STATS_READ_OPS: - return builder.readOps(parser.nextIntValue(0)); - case ResponseFields.STATS_WRITE_OPS: - return builder.writeOps(parser.nextIntValue(0)); - case ResponseFields.STATS_QUERY_TIME_MS: - return builder.queryTimeMs(parser.nextIntValue(0)); - case ResponseFields.STATS_PROCESSING_TIME_MS: - return builder.processingTimeMs(parser.nextIntValue(0)); - case ResponseFields.STATS_CONTENTION_RETRIES: - return builder.contentionRetries(parser.nextIntValue(0)); - case ResponseFields.STATS_STORAGE_BYTES_READ: - return builder.storageBytesRead(parser.nextIntValue(0)); - case ResponseFields.STATS_STORAGE_BYTES_WRITE: - return builder.storageBytesWrite(parser.nextIntValue(0)); - case ResponseFields.STATS_RATE_LIMITS_HIT: - List limits = new ArrayList<>(); - if (parser.nextToken() == START_ARRAY) { - while (parser.nextToken() == VALUE_STRING) { - limits.add(parser.getValueAsString()); - } - } - return builder.rateLimitsHit(limits); - default: - throw new ClientResponseException("Unknown field " + fieldName); - } - } - - /** - * Parse QueryStats from a JsonParser. - * - * @param parser the JsonParser to consume - * @return a QueryStats object containing the parsed stats - * @throws IOException thrown from the JsonParser - */ - public static QueryStats parseStats(final JsonParser parser) - throws IOException { - if (parser.nextToken() == START_OBJECT) { - Builder builder = builder(); - while (parser.nextToken() == FIELD_NAME) { - builder = parseField(builder, parser); - } - return builder.build(); - } else if (parser.nextToken() == VALUE_NULL) { - return null; - } else { - throw new ClientResponseException( - "Query stats should be an object or null, not " - + parser.getCurrentToken()); - } - } - - private static String statString(final String name, final Object value) { - return String.join(": ", name, String.valueOf(value)); - } - - @Override - public String toString() { - if (this.stringValue == null) { - this.stringValue = String.join(", ", - statString("compute", computeOps), - statString("read", readOps), - statString("write", writeOps), - statString("queryTime", queryTimeMs), - statString("retries", contentionRetries), - statString("storageRead", storageBytesRead), - statString("storageWrite", storageBytesWrite), - statString("limits", rateLimitsHit) - ); - } - return this.stringValue; - } } diff --git a/src/main/java/com/fauna/response/QuerySuccess.java b/src/main/java/com/fauna/response/QuerySuccess.java index 654f9ba2..6f76449a 100644 --- a/src/main/java/com/fauna/response/QuerySuccess.java +++ b/src/main/java/com/fauna/response/QuerySuccess.java @@ -7,10 +7,10 @@ public final class QuerySuccess extends QueryResponse { private final T data; private final String staticType; - public QuerySuccess(Builder builder) { + public QuerySuccess(final Builder builder) { super(builder); - this.data = builder.data; - this.staticType = builder.staticType; + this.data = builder.getData(); + this.staticType = builder.getStaticType(); } public T getData() { From 1fc6db2abc8a7b0eaa35f61343d2bb267b5dd2ec Mon Sep 17 00:00:00 2001 From: James Rodewig Date: Wed, 6 Nov 2024 10:58:34 -0500 Subject: [PATCH 2/2] Review feedback --- .../com/fauna/response/ConstraintFailure.java | 20 +++++++++++-------- .../java/com/fauna/response/ErrorInfo.java | 17 +++++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/fauna/response/ConstraintFailure.java b/src/main/java/com/fauna/response/ConstraintFailure.java index 04b9b9ba..f01a9481 100644 --- a/src/main/java/com/fauna/response/ConstraintFailure.java +++ b/src/main/java/com/fauna/response/ConstraintFailure.java @@ -21,11 +21,15 @@ public final class ConstraintFailure { private final PathElement[][] paths; /** - * Initialize a new ConstraintFailure instance. + * Initialize a new ConstraintFailure instance. Queries that fail a check + * or unique + * constraint> return a constraint failure. * - * @param message The constraint failure message. - * @param name The constraint failure name. - * @param paths The constraint failure paths. + * @param message Human-readable description of the constraint failure. + * @param name Name of the failed constraint. + * @param paths A list of paths where the constraint failure occurred. */ public ConstraintFailure( final String message, @@ -135,7 +139,7 @@ public Optional getName() { } /** - * Gets an optional of path elements related to the constraint failure. + * Gets an optional path elements related to the constraint failure. * * @return An array of arrays of PathElements. */ @@ -235,7 +239,7 @@ public static PathElement parse(final JsonParser parser) /** * Tests whether the PathElement stores a string or an integer. * - * @return True if it's a string, else false. + * @return If it's a string, true. Otherwise, false. */ public boolean isString() { return sVal != null; @@ -276,7 +280,7 @@ public static class Builder { * Sets a message on the builder. * * @param message The message to set. - * @return this + * @return this. */ public Builder message(final String message) { this.message = message; @@ -287,7 +291,7 @@ public Builder message(final String message) { * Sets a name on the builder. * * @param name The name to set. - * @return this + * @return this. */ public Builder name(final String name) { this.name = name; diff --git a/src/main/java/com/fauna/response/ErrorInfo.java b/src/main/java/com/fauna/response/ErrorInfo.java index 7883a29e..1d288d95 100644 --- a/src/main/java/com/fauna/response/ErrorInfo.java +++ b/src/main/java/com/fauna/response/ErrorInfo.java @@ -32,10 +32,17 @@ public class ErrorInfo { /** * Initializes a new ErrorInfo. * - * @param code The Fauna error code - * @param message The error message - * @param constraintFailures The constraint failures, if any - * @param abort A abort JSON node of the response, if any + * @param code The Fauna + * error code. + * @param message A short, human-readable description of the + * error. + * @param constraintFailures The constraint failures for the error, if any. + * Only present if the error code is + * `constraint_failure`. + * @param abort A user-defined error message passed using an + * FQL `abort()` method call. Only present if the error + * code is `abort`. */ public ErrorInfo( final String code, @@ -142,7 +149,7 @@ public Optional getConstraintFailures() { } /** - * Gets the abort JSON node. + * Gets the user-defined abort error message as a JSON node. * * @return An optional TreeNode with the abort data. */