Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BT-4418] FaunaParser Integer values #16

Merged
merged 8 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 78 additions & 4 deletions faunaJava/src/main/java/com/fauna/serialization/FaunaParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public class FaunaParser {
private FaunaTokenType bufferedFaunaTokenType;
private String taggedTokenValue;

private enum TokenTypeInternal {
START_ESCAPED_OBJECT
}

public FaunaParser(InputStream body) throws IOException {
JsonFactory factory = new JsonFactory();
this.jsonParser = factory.createParser(body);
Expand All @@ -52,8 +56,8 @@ public FaunaParser(JsonParser jsonParser) {
currentFaunaTokenType = NONE;
}

public JsonToken getCurrentTokenType() {
return jsonParser.currentToken();
public FaunaTokenType getCurrentTokenType() {
return currentFaunaTokenType;
}

private final Set<FaunaTokenType> closers = new HashSet<>(Arrays.asList(
Expand All @@ -64,7 +68,7 @@ public JsonToken getCurrentTokenType() {
END_ARRAY
));

public boolean read() {
public boolean read() throws IOException {
taggedTokenValue = null;

if (bufferedFaunaTokenType != null) {
Expand All @@ -86,6 +90,9 @@ public boolean read() {
case VALUE_STRING:
currentFaunaTokenType = FaunaTokenType.STRING;
break;
case START_OBJECT:
handleStartObject();
break;
default:
throw new SerializationException(
"Unhandled JSON token type " + currentToken + ".");
Expand All @@ -97,6 +104,55 @@ public boolean read() {
return true;
}

private void handleStartObject() throws IOException {
advanceTrue();

switch (jsonParser.currentToken()) {
case FIELD_NAME:
switch (jsonParser.getText()) {
case INT_TAG:
handleTaggedString(FaunaTokenType.INT);
break;
case DATE_TAG:
case DOC_TAG:
case DOUBLE_TAG:
case LONG_TAG:
case MOD_TAG:
case OBJECT_TAG:
case REF_TAG:
case SET_TAG:
case TIME_TAG:
throw new SerializationException(
"Token not implemented: " + jsonParser.currentToken());
default:
bufferedFaunaTokenType = FaunaTokenType.FIELD_NAME;
tokenStack.push(FaunaTokenType.START_OBJECT);
currentFaunaTokenType = FaunaTokenType.START_OBJECT;
break;
}
break;
case END_OBJECT:
pchitolina-fauna marked this conversation as resolved.
Show resolved Hide resolved
throw new SerializationException(
"Token not implemented: " + jsonParser.currentToken());
default:
throw new SerializationException(
"Unexpected token following StartObject: " + jsonParser.currentToken());
}
}

private void handleTaggedString(FaunaTokenType token) throws IOException {
advanceTrue();
currentFaunaTokenType = token;
taggedTokenValue = jsonParser.getText();
advance();
}

private void advanceTrue() {
if (!advance()) {
throw new SerializationException("Unexpected end of underlying JSON reader.");
}
}

private boolean advance() {
try {
return Objects.nonNull(jsonParser.nextToken());
Expand All @@ -105,11 +161,29 @@ private boolean advance() {
}
}

private void validateTaggedType(FaunaTokenType type) {
if (currentFaunaTokenType != type || taggedTokenValue == null
|| !(taggedTokenValue instanceof String)) {
throw new IllegalStateException(
"CurrentTokenType is a " + currentFaunaTokenType.toString() +
", not a " + type.toString() + ".");
}
}

public String getValueAsString() {
try {
return jsonParser.getValueAsString();
} catch (IOException e) {
throw new RuntimeException("Error reading current token as String", e);
throw new RuntimeException("Error getting the current token as String", e);
}
}

public Integer getValueAsInt() {
pchitolina-fauna marked this conversation as resolved.
Show resolved Hide resolved
validateTaggedType(FaunaTokenType.INT);
try {
return Integer.parseInt(taggedTokenValue);
} catch (NumberFormatException e) {
throw new RuntimeException("Error getting the current token as Integer", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.fauna.query.template;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class FaunaTemplateTest {

Expand Down Expand Up @@ -63,16 +62,4 @@ void testTemplates_WithEscapes() {
assertEquals(TemplatePartType.LITERAL, expanded.get(1).getType());
}

@Test
void testTemplates_WithUnsupportedIdentifiers() {
FaunaTemplate template = new FaunaTemplate("let x = ${かわいい}");
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
List<FaunaTemplate.TemplatePart> expanded = new ArrayList<>();
template.forEach(expanded::add);
});
String expectedMessage = "Invalid placeholder in template: line 1, col 9";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}
pchitolina-fauna marked this conversation as resolved.
Show resolved Hide resolved

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.fauna.common.enums.FaunaTokenType;
import com.fauna.exception.SerializationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -28,19 +30,51 @@ public void testGetValueAsString() throws IOException {
assertReader(reader, expectedTokens);
}

@Test
public void testGetValueAsInt() throws IOException {
String s = "{\"@int\": \"123\"}";
InputStream inputStream = new ByteArrayInputStream(s.getBytes());
FaunaParser reader = new FaunaParser(inputStream);

List<Map.Entry<FaunaTokenType, Object>> expectedTokens = List.of(
Map.entry(FaunaTokenType.INT, 123)
);

assertReader(reader, expectedTokens);

String invalidJson = "{\"@int\": \"abc\"}";
InputStream invalidInputStream = new ByteArrayInputStream(invalidJson.getBytes());
FaunaParser invalidReader = new FaunaParser(invalidInputStream);

assertThrows(RuntimeException.class, invalidReader::getValueAsInt);
}

@Test
public void testUnexpectedEndDuringAdvance() throws IOException {

String json = "{\"@int\": \"123\"";
InputStream inputStream = new ByteArrayInputStream(json.getBytes());
FaunaParser reader = new FaunaParser(inputStream);

assertThrows(SerializationException.class, reader::read);
pnwpedro marked this conversation as resolved.
Show resolved Hide resolved
}

private static void assertReader(FaunaParser reader,
List<Map.Entry<FaunaTokenType, Object>> tokens) {
List<Map.Entry<FaunaTokenType, Object>> tokens) throws IOException {
for (Map.Entry<FaunaTokenType, Object> entry : tokens) {
reader.read();
assertNotNull(entry.getKey());
assertNotNull(reader.getCurrentTokenType());
assertEquals(entry.getKey(), FaunaTokenType.STRING);
assertEquals(entry.getKey(), reader.getCurrentTokenType());

switch (entry.getKey()) {
case FIELD_NAME:
case STRING:
assertEquals(entry.getValue(), reader.getValueAsString());
break;
case INT:
assertEquals(entry.getValue(), reader.getValueAsInt());
break;
default:
assertNull(entry.getValue() == null);
break;
Expand Down
Loading