Skip to content

Commit

Permalink
Merge branch 'main' into federation-resolvers
Browse files Browse the repository at this point in the history
  • Loading branch information
RoMiRoSSaN authored Sep 26, 2024
2 parents 4550ff2 + 485dc50 commit 85f61e8
Show file tree
Hide file tree
Showing 37 changed files with 1,102 additions and 571 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ jobs:
- name: checkout Quarkus repository
uses: actions/checkout@v2
with:
repository: quarkusio/quarkus
ref: main
repository: jmartisk/quarkus
ref: smallrye-graphql-2.11
path: quarkus

- uses: actions/setup-java@v4
Expand Down
10 changes: 5 additions & 5 deletions client/implementation-vertx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>io.smallrye</groupId>
Expand All @@ -65,11 +70,6 @@
<artifactId>smallrye-graphql-client-model-builder</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import java.util.List;
import java.util.Map;

import org.eclipse.microprofile.graphql.Name;
import org.jboss.logging.Logger;

import io.smallrye.graphql.api.Namespace;
import io.smallrye.graphql.client.impl.ErrorMessageProvider;
import io.smallrye.graphql.client.impl.GraphQLClientConfiguration;
import io.smallrye.graphql.client.impl.GraphQLClientsConfiguration;
Expand Down Expand Up @@ -145,6 +147,14 @@ public VertxTypesafeGraphQLClientBuilder websocketInitializationTimeout(Integer

@Override
public <T> T build(Class<T> apiClass) {
Name nameAnnotation = apiClass.getAnnotation(Name.class);
Namespace namespaceAnnotation = apiClass.getAnnotation(Namespace.class);

if (nameAnnotation != null && namespaceAnnotation != null) {
throw new RuntimeException("You can only use one of the annotations - @Name or @Namespace " +
"over the GraphQLClientApi interface. Please, fix the following interface: " + apiClass.getName());
}

if (this.options == null) {
this.options = new WebClientOptions();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ private JsonObject request(MethodInvocation method) {
}
request.add("query", query);
request.add("variables", variables(method));
request.add("operationName", method.getName());
request.add("operationName", method.getOperationName());
JsonObject result = request.build();
log.tracef("full graphql request: %s", result.toString());
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,11 @@ public QueryBuilder(MethodInvocation method) {
public String build() {
StringBuilder request = new StringBuilder(method.getOperationTypeAsString());
request.append(" ");
request.append(method.getName());
request.append(method.getOperationName());
if (method.hasValueParameters())
request.append(method.valueParameters().map(this::declare).collect(joining(", ", "(", ")")));

String groupName = method.getGroupName();
if (groupName != null) {
request.append(" { ");
request.append(groupName);
}
method.getNamespaces().forEach(namespace -> request.append(" { ").append(namespace));

if (method.isSingle()) {
request.append(" { ");
Expand All @@ -45,11 +41,11 @@ public String build() {

request.append(fields(method.getReturnType()));

if (method.isSingle())
if (method.isSingle()) {
request.append(" }");
}

if (groupName != null)
request.append(" } ");
request.append(" }".repeat(method.getNamespaces().size()));

return request.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ public Object read() {
private JsonObject readData() {
if (!response.containsKey("data") || response.isNull("data"))
return null;
String groupName = method.getGroupName();
JsonObject data = groupName != null
? response.getJsonObject("data").getJsonObject(groupName)
: response.getJsonObject("data");

JsonObject data = response.getJsonObject("data");
for (String namespace : method.getNamespaces()) {
data = data.getJsonObject(namespace);
}

if (method.isSingle() && !data.containsKey(method.getName()))
throw new InvalidResponseException("No data for '" + method.getName() + "'");
return data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

Expand All @@ -23,6 +24,7 @@
import org.eclipse.microprofile.graphql.Name;
import org.eclipse.microprofile.graphql.Query;

import io.smallrye.graphql.api.Namespace;
import io.smallrye.graphql.api.Subscription;
import io.smallrye.graphql.client.core.OperationType;
import io.smallrye.graphql.client.model.MethodKey;
Expand All @@ -36,14 +38,16 @@ public static MethodInvocation of(Method method, Object... args) {
private final TypeInfo type;
private final Method method;
private final Object[] parameterValues;
private final String groupName;
private final List<String> namespaces;
private final String operationName;
private List<ParameterInfo> parameters;

private MethodInvocation(TypeInfo type, Method method, Object[] parameterValues) {
this.type = type;
this.method = method;
this.parameterValues = parameterValues;
this.groupName = readGroupName(method);
this.namespaces = readNamespaces(method);
this.operationName = readOperationName(this.namespaces);
}

@Override
Expand Down Expand Up @@ -262,18 +266,41 @@ public String getOperationTypeAsString() {
}
}

public String getGroupName() {
return groupName;
public List<String> getNamespaces() {
return namespaces;
}

private String readGroupName(Method method) {
Name annotation = method.getDeclaringClass().getAnnotation(Name.class);
if (annotation != null) {
String groupName = annotation.value().trim();
if (!groupName.isEmpty()) {
return groupName;
public String getOperationName() {
return operationName;
}

private List<String> readNamespaces(Method method) {
if (method.getDeclaringClass().isAnnotationPresent(Namespace.class)) {
String[] names = method.getDeclaringClass().getAnnotation(Namespace.class).value();
if (names.length > 0) {
return List.of(names);
}
} else if (method.getDeclaringClass().isAnnotationPresent(Name.class)) {
String name = method.getDeclaringClass().getAnnotation(Name.class).value();
if (!name.isBlank()) {
return List.of(name);
}
}
return List.of();
}

private String readOperationName(List<String> names) {
if (names.isEmpty()) {
return getName();
} else {
String namespace = names.stream()
.map(this::makeFirstLetterUppercase)
.collect(Collectors.joining());
return namespace + makeFirstLetterUppercase(getName());
}
return null;
}

private String makeFirstLetterUppercase(String value) {
return value.substring(0, 1).toUpperCase() + value.substring(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ private static Map<DotName, AnnotationInstance> getAnnotationsWithFilter(Type ty
public static final DotName NON_BLOCKING = DotName.createSimple("io.smallrye.common.annotation.NonBlocking");

// SmallRye GraphQL Annotations (Experimental)
public static final DotName NAMESPACE = DotName.createSimple("io.smallrye.graphql.api.Namespace");
public static final DotName TO_SCALAR = DotName.createSimple("io.smallrye.graphql.api.ToScalar"); // TODO: Remove
public static final DotName ADAPT_TO_SCALAR = DotName.createSimple("io.smallrye.graphql.api.AdaptToScalar");
public static final DotName ADAPT_WITH = DotName.createSimple("io.smallrye.graphql.api.AdaptWith");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package io.smallrye.graphql.client.model;

import static io.smallrye.graphql.client.model.Annotations.GRAPHQL_CLIENT_API;
import static io.smallrye.graphql.client.model.Annotations.NAME;
import static io.smallrye.graphql.client.model.Annotations.NAMESPACE;
import static io.smallrye.graphql.client.model.ScanningContext.getIndex;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
Expand Down Expand Up @@ -56,6 +59,8 @@ private ClientModels generateClientModels() {
Collection<AnnotationInstance> graphQLApiAnnotations = getIndex()
.getAnnotations(GRAPHQL_CLIENT_API);

validateNamespaceAnnotations(graphQLApiAnnotations);

graphQLApiAnnotations.forEach(graphQLApiAnnotation -> {
ClientModel operationMap = new ClientModel();
ClassInfo apiClass = graphQLApiAnnotation.target().asClass();
Expand All @@ -75,6 +80,19 @@ private ClientModels generateClientModels() {
return clientModels;
}

private void validateNamespaceAnnotations(Collection<AnnotationInstance> graphQLApiAnnotations) {
List<String> errorInterfaces = graphQLApiAnnotations.stream()
.map(annotation -> annotation.target().asClass())
.filter(classInfo -> classInfo.hasDeclaredAnnotation(NAMESPACE) && classInfo.hasDeclaredAnnotation(NAME))
.map(classInfo -> classInfo.name().toString())
.collect(Collectors.toList());
if (!errorInterfaces.isEmpty()) {
throw new RuntimeException("You can only use one of the annotations - @Name or @Namespace " +
"over the GraphQLClientApi interface. Please, fix the following interfaces: " +
String.join(", ", errorInterfaces));
}
}

/**
* Retrieves all methods, including those from superclasses (interfaces).
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,12 @@ public QueryBuilder(MethodInfo method) {
public String build() {
StringBuilder request = new StringBuilder(method.getOperationTypeAsString());
request.append(" ");
request.append(method.getName()); // operationName
request.append(method.getOperationName());
if (method.hasValueParameters()) {
request.append(method.valueParameters().stream().map(method::declare).collect(joining(", ", "(", ")")));
}

String groupName = method.getGroupName();
if (groupName != null) {
request.append(" { ");
request.append(groupName);
}
method.getNamespaces().forEach(namespace -> request.append(" { ").append(namespace));

if (method.isSingle()) {
request.append(" { ");
Expand All @@ -61,11 +57,11 @@ public String build() {

request.append(method.fields(method.getReturnType()));

if (method.isSingle())
if (method.isSingle()) {
request.append(" }");
}

if (groupName != null)
request.append(" } ");
request.append(" }".repeat(method.getNamespaces().size()));

return request.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static io.smallrye.graphql.client.model.Annotations.MULTIPLE;
import static io.smallrye.graphql.client.model.Annotations.MUTATION;
import static io.smallrye.graphql.client.model.Annotations.NAME;
import static io.smallrye.graphql.client.model.Annotations.NAMESPACE;
import static io.smallrye.graphql.client.model.Annotations.QUERY;
import static io.smallrye.graphql.client.model.Annotations.SUBCRIPTION;
import static io.smallrye.graphql.client.model.ScanningContext.getIndex;
Expand Down Expand Up @@ -37,7 +38,8 @@ public class OperationModel implements NamedElement {
private final Stack<String> expressionStack = new Stack<>();
private Stack<TypeModel> rawParametrizedTypes = new Stack<>();
private final List<DirectiveInstance> directives;
private final String groupName;
private final String operationName;
private final List<String> namespaces;

/**
* Creates a new {@code OperationModel} instance based on the provided Jandex {@link MethodInfo}.
Expand All @@ -51,7 +53,8 @@ public class OperationModel implements NamedElement {
getDirectiveLocation(), AnnotationTarget.Kind.METHOD)
.map(DirectiveInstance::of)
.collect(toList());
this.groupName = readGroupName(method);
this.namespaces = readNamespaces(method);
this.operationName = readOperationName(this.namespaces);
}

/**
Expand Down Expand Up @@ -399,23 +402,42 @@ private boolean isRawParametrizedType(TypeModel type) {
return type.isCustomParametrizedType() && !type.getFirstRawType().isTypeVariable();
}

public String getGroupName() {
return groupName;
public List<String> getNamespaces() {
return namespaces;
}

private String readGroupName(MethodInfo method) {
List<AnnotationInstance> annotationInstances = method.declaringClass().annotations(NAME);
for (AnnotationInstance annotationInstance : annotationInstances) {
if (annotationInstance.target().kind() == AnnotationTarget.Kind.CLASS) {
if (annotationInstance.target().asClass().name().equals(method.declaringClass().name())) {
String groupName = annotationInstance.value().asString().trim();
if (!groupName.isEmpty()) {
return groupName;
}
}
public String getOperationName() {
return operationName;
}

private List<String> readNamespaces(MethodInfo method) {
if (method.declaringClass().hasDeclaredAnnotation(NAMESPACE)) {
String[] names = method.declaringClass().declaredAnnotation(NAMESPACE).value().asStringArray();
if (names.length > 0) {
return List.of(names);
}
} else if (method.declaringClass().hasDeclaredAnnotation(NAME)) {
String value = method.declaringClass().declaredAnnotation(NAME).value().asString();
if (!value.isEmpty()) {
return List.of(value);
}
}
return List.of();
}

private String readOperationName(List<String> names) {
if (names.isEmpty()) {
return getName();
} else {
String namespace = names.stream()
.map(this::makeFirstLetterUppercase)
.collect(joining());
return namespace + makeFirstLetterUppercase(getName());
}
return null;
}

private String makeFirstLetterUppercase(String value) {
return value.substring(0, 1).toUpperCase() + value.substring(1);
}

private String fieldsFragment(TypeModel type) {
Expand Down
Loading

0 comments on commit 85f61e8

Please sign in to comment.