Skip to content

Commit

Permalink
QueryVal, Query Composition, and circular ref bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pnwpedro committed Aug 30, 2024
1 parent 3ec1417 commit d26e4df
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 16 deletions.
3 changes: 3 additions & 0 deletions src/main/java/com/fauna/codec/DefaultCodecProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
import com.fauna.codec.codecs.QueryCodec;
import com.fauna.codec.codecs.QueryLiteralCodec;
import com.fauna.codec.codecs.QueryObjCodec;
import com.fauna.codec.codecs.QueryValCodec;
import com.fauna.query.builder.Query;
import com.fauna.query.builder.QueryArr;
import com.fauna.query.builder.QueryLiteral;
import com.fauna.query.builder.QueryObj;
import com.fauna.query.builder.QueryVal;
import com.fauna.types.BaseDocument;
import com.fauna.types.Document;
import com.fauna.types.NamedDocument;
Expand All @@ -38,6 +40,7 @@ public DefaultCodecProvider(CodecRegistry registry) {
registry.put(CodecRegistryKey.from(Query.class), new QueryCodec(this));
registry.put(CodecRegistryKey.from(QueryObj.class), new QueryObjCodec(this));
registry.put(CodecRegistryKey.from(QueryArr.class), new QueryArrCodec(this));
registry.put(CodecRegistryKey.from(QueryVal.class), new QueryValCodec(this));
registry.put(CodecRegistryKey.from(QueryLiteral.class), new QueryLiteralCodec());

var bdc = new BaseDocumentCodec(this);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/fauna/codec/codecs/ClassCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public ClassCodec(Class<T> ty, CodecProvider provider) {
}

var ta = attr.typeArgument() != void.class ? attr.typeArgument() : null;
var codec = provider.get(field.getType(), ta);
FieldInfo info = new FieldInfo(field, attr.name(), codec);
// Don't init the codec here because of potential circular references; instead use a provider.
FieldInfo info = new FieldInfo(field, attr.name(), ta, provider);
fieldsList.add(info);
byNameMap.put(info.getName(), info);
}
Expand Down Expand Up @@ -86,7 +86,7 @@ public void encode(UTF8FaunaGenerator gen, T obj) throws IOException {
try {
fi.getProperty().setAccessible(true);
@SuppressWarnings("unchecked")
T value = (T) fi.getProperty().get(obj);
T value = obj != null ? (T) fi.getProperty().get(obj) : null;
@SuppressWarnings("unchecked")
Codec<T> codec = fi.getCodec();
codec.encode(gen, value);
Expand Down
23 changes: 17 additions & 6 deletions src/main/java/com/fauna/mapping/FieldInfo.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package com.fauna.mapping;

import com.fauna.codec.Codec;
import com.fauna.codec.CodecProvider;

import java.lang.reflect.Field;

public final class FieldInfo {

private final String name;
private final Field property;
private final Class<?> type;
private final Class<?> typeArg;
private final CodecProvider provider;
private Codec<?> codec;

public FieldInfo(Field prop, String name, Codec codec) {
public FieldInfo(Field prop, String name, Class<?> typeArg, CodecProvider provider) {
this.name = name;
this.property = prop;
this.type = prop.getType();
this.codec = codec;
this.typeArg = typeArg;
this.provider = provider;
}

public String getName() {
Expand All @@ -27,10 +29,19 @@ public Field getProperty() {
}

public Class<?> getType() {
return type;
return property.getType();
}

public Codec getCodec() {
return this.codec;
if (codec != null) return codec;

synchronized (this) {
// check again in case it was set by another thread
if (codec != null) return codec;

codec = provider.get(property.getType(), typeArg);
}

return codec;
}
}
8 changes: 3 additions & 5 deletions src/main/java/com/fauna/query/builder/Query.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.fauna.query.builder;

import com.fauna.codec.CodecProvider;
import com.fauna.query.template.FaunaTemplate;
import com.fauna.codec.UTF8FaunaGenerator;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Spliterator;
Expand All @@ -15,7 +12,7 @@
* Represents a Fauna query that is constructed from fragments.
* This class allows the building of queries from literal and variable parts.
*/
public class Query{
public class Query extends QueryFragment<QueryFragment[]> {

private final QueryFragment[] fql;

Expand Down Expand Up @@ -62,9 +59,10 @@ public static Query fql(String query) throws IllegalArgumentException {
/**
* Retrieves the list of fragments that make up this query.
*
* @return a list of Fragments.
* @return an array of Fragments.
* @throws IllegalArgumentException if a template variable does not have a corresponding entry in the provided args.
*/
@Override
public QueryFragment[] get() {
return this.fql;
}
Expand Down
9 changes: 9 additions & 0 deletions src/test/java/com/fauna/beans/Circular.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.fauna.beans;

public class Circular {
public static class Inner {
public Circular outer;
}

public Inner inner;
}
9 changes: 9 additions & 0 deletions src/test/java/com/fauna/codec/DefaultCodecProviderTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.fauna.codec;

import com.fauna.beans.Circular;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand Down Expand Up @@ -44,4 +45,12 @@ public void get_generatesListCodecForImmutableList() {
assertNotNull(codec);
assertEquals(List.class, codec.getCodecClass());
}

@Test
@SuppressWarnings({"rawtypes", "unchecked"})
public void get_generateForClassWithCircularRef() {
Codec<Circular> codec = cp.get(Circular.class, null);
assertNotNull(codec);
assertEquals(Circular.class, codec.getCodecClass());
}
}
4 changes: 2 additions & 2 deletions src/test/java/com/fauna/query/builder/QueryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ public void testQueryBuilderValues() {
}

@Test
public void testQueryBuilderSubQueries() {
public void testQueryBuilderSubQueries() throws IOException {
Map<String, Object> user = Map.of(
"name", "Dino",
"age", 0,
"birthdate", LocalDate.of(2023, 2, 24));

Query inner = fql("let x = ${my_var}", Map.of("my_var", user));
Query actual = fql("${inner}\nx { name }", Map.of("inner", inner));
QueryFragment[] expected = new QueryFragment[]{new QueryVal(inner), new QueryLiteral("\nx { name }")};
QueryFragment[] expected = new QueryFragment[]{inner, new QueryLiteral("\nx { name }")};
assertArrayEquals(expected, actual.get());
}

Expand Down

0 comments on commit d26e4df

Please sign in to comment.