Skip to content

Support for prefixes and suffixes on generated java classes #155

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

Merged
merged 30 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8a02542
Testing a maven workflow
agesenm-ELS Oct 12, 2022
7507d14
Update maven.yml
agesenm-ELS Oct 12, 2022
0d19824
Update maven.yml
agesenm-ELS Oct 12, 2022
de89142
Added some missing initialization to a broken test
agesenm-ELS Oct 13, 2022
2fc00a1
Adds configuration for prefixes and suffixes for the generated classes
agesenm-ELS Oct 13, 2022
abba3e4
Adds configuration for prefixes and suffixes for the generated classes
agesenm-ELS Oct 13, 2022
9334e38
Use the java name instead of the graphql name when generating "implem…
agesenm-ELS Oct 13, 2022
79628be
Update maven.yml
agesenm-ELS Oct 13, 2022
fee8412
Merge branch 'master' into prefixes-and-suffixes-for-java-classes
agesenm-ELS Oct 13, 2022
396ad7a
Update maven.yml
agesenm-ELS Oct 13, 2022
900b8ac
Merge branch 'master' into prefixes-and-suffixes-for-java-classes
agesenm-ELS Oct 13, 2022
a7ffbc3
Update maven.yml
agesenm-ELS Oct 13, 2022
e75488c
Merge remote-tracking branch 'origin/master' into prefixes-and-suffix…
agesenm-ELS Oct 13, 2022
1ea35fb
Adds tests for suffix and prefix configuration and code generation
agesenm-ELS Oct 13, 2022
e305295
Typo fix
agesenm-ELS Oct 13, 2022
db1355d
Merge pull request #1 from agesenm-ELS/prefixes-and-suffixes-for-java…
agesenm-ELS Oct 13, 2022
6e699e6
Removed CI workflow
agesenm-ELS Oct 13, 2022
ff0093e
Wiring should map from Graphql type names instead of java names.
agesenm-ELS Oct 14, 2022
b9f1569
Wiring should map from Graphql type names instead of java names.
agesenm-ELS Oct 24, 2022
5d49d48
Merge branch 'graphql-java-generator:master' into master
agesenm-ELS Oct 24, 2022
8ba4074
Prefix-suffix support: Use name() instead of javaName() for utility c…
agesenm-ELS Oct 25, 2022
cbe2159
Prefix-suffix support: Use javaName() instead of name() for @Type ann…
agesenm-ELS Oct 25, 2022
d3dba26
Adds a sub-module for integration that configured prefixes and suffix…
agesenm-ELS Oct 25, 2022
f5cce60
Adds a sub-module for integration that configured prefixes and suffix…
agesenm-ELS Oct 25, 2022
b3564ab
Elaborates documentation of prefix/suffix configuration parameters
agesenm-ELS Oct 25, 2022
fc4f96e
Add a client type mapping generated file for mapping from graphql typ…
agesenm-ELS Nov 1, 2022
1515e94
Use the new generated GraphQLTypeMapping to get the java class for a …
agesenm-ELS Nov 1, 2022
6de62b1
Added prefixes and suffixes to client integration tests
agesenm-ELS Nov 1, 2022
574c986
Added prefixes and suffixes to server integration tests
agesenm-ELS Nov 1, 2022
6dbf813
Removed prefix-suffix module no longer needed after allGraphQLCases c…
agesenm-ELS Nov 1, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ public Object getAliasValue(JsonParser parser, Field targetField, TreeNode value
String typename = ((TextNode) value.get("__typename")).asText();
Class<?> clazz;
try {
clazz = Class.forName(graphQLObjectsPackage + '.' + typename);
} catch (ClassNotFoundException e) {
clazz = GraphqlClientUtils.graphqlClientUtils.getClass(graphQLObjectsPackage, typename, null);
} catch (RuntimeException e) {
throw new JsonMappingException(parser, e.getMessage(), e);
}
return objectMapper.treeToValue(value, clazz);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -188,7 +189,7 @@ public boolean isScalar(AccessibleObject fieldOrMethod) throws GraphQLRequestPre

/**
* Retrieves a class for a given classname. For standard GraphQL types (Int, Boolean...) the good package is used
* (java.lang, java.lang, java.util...). For others, the class is searched in the given package name.
* (java.lang, java.lang, java.util...). For others, the class is retrieved from the generated GraphQLTypeMapping.
*
* @param packageName
* The name of the package, where the code has been generated.
Expand All @@ -212,20 +213,34 @@ else if ("Float".equals(graphQLTypeName) || "Double".equals(graphQLTypeName))
return Double.class;

// Then custom scalars
CustomScalar customScalar = CustomScalarRegistryImpl.getCustomScalarRegistry(schema)
.getCustomScalar(graphQLTypeName);
if (customScalar != null) {
return customScalar.getValueClazz();
if (schema != null) {
CustomScalar customScalar = CustomScalarRegistryImpl.getCustomScalarRegistry(schema)
.getCustomScalar(graphQLTypeName);
if (customScalar != null) {
return customScalar.getValueClazz();
}
}

// Then other GraphQL types. This types should be linked to a generated java class. So we search for a class of
// this name in the given package.
String parameterClassname = packageName + "." + graphqlUtils.getJavaName(graphQLTypeName);
try {
return Class.forName(parameterClassname);
// lookup the java class corresponding to the graphql type from the generated GraphQLTypeMapping
return (Class<?>) getClass().getClassLoader()
.loadClass(packageName + ".GraphQLTypeMapping")
.getMethod("getJavaClass", String.class)
.invoke(null, graphQLTypeName);
} catch (ClassNotFoundException e) {
// If GraphqlTypeMapping does not exist (in some tests), fallback to using the type name.
final String className = packageName + "." + GraphqlUtils.graphqlUtils.getJavaName(graphQLTypeName);
try {
return getClass().getClassLoader().loadClass(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Could not load class '" + className + "' for type '" + graphQLTypeName + "'", e);
}
} catch (ClassCastException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(
"Couldn't find the class (" + parameterClassname + ") of the type '" + graphQLTypeName + "'", e);
"Could not get the class for type '" + graphQLTypeName + "' from '" + (packageName + ".GraphQLTypeMapping") + "'" , e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import java.util.List;
import java.util.Map;

import com.graphql_java_generator.client.GraphqlClientUtils;
import com.graphql_java_generator.client.directive.Directive;
import com.graphql_java_generator.exception.GraphQLRequestExecutionException;
import com.graphql_java_generator.exception.GraphQLRequestPreparationException;
import com.graphql_java_generator.util.GraphqlUtils;

/**
* @author etienne-sf
Expand Down Expand Up @@ -97,14 +97,12 @@ public Fragment(QueryTokenizer qt, Map<Class<?>, Map<String, Field>> aliasFields

// Ok, we're ready to read the fragment content
if (typeName != null) {
// If the typeName was provided in the fragment definition, then we load the clas that represents the
// If the typeName was provided in the fragment definition, then we load the class that represents the
// GraphQL type on which the fragment applies. This allows to check the input parameters, and their type
String classname = packageName + "." + GraphqlUtils.graphqlUtils.getJavaName(typeName);
try {
clazz = getClass().getClassLoader().loadClass(classname);
} catch (ClassNotFoundException e) {
throw new GraphQLRequestPreparationException(
"Could not load class '" + classname + "' for type '" + typeName + "'", e);
clazz = GraphqlClientUtils.graphqlClientUtils.getClass(packageName, typeName, schema);
} catch (RuntimeException e) {
throw new GraphQLRequestPreparationException(e.getMessage(), e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.util.TreeSet;
import java.util.UUID;

import com.graphql_java_generator.domain.client.forum.CustomScalarRegistryInitializer;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
Expand All @@ -38,6 +40,11 @@
@Execution(ExecutionMode.CONCURRENT)
class GraphqlUtilsTest {

@BeforeAll
public static void initCustomScalarRegistry() {
CustomScalarRegistryInitializer.initCustomScalarRegistry();
}

GraphqlUtils graphqlUtils = new GraphqlUtils();

/** A test class for {@link GraphqlUtilsTest#test_addImports()} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum CodeTemplate {
SPRING_CONFIGURATION_CLASS(CodeTemplateScope.CLIENT, "templates/client_spring_configuration.vm.java"), //
SUBSCRIPTION(CodeTemplateScope.CLIENT, "templates/client_subscription_type.vm.java"), //
SUBSCRIPTION_EXECUTOR(CodeTemplateScope.CLIENT, "templates/client_subscription_executor.vm.java"), //
TYPE_MAPPING(CodeTemplateScope.CLIENT, "templates/client_type_mapping.vm.java"), //

// Server files (alphabetic order)
BATCH_LOADER_DELEGATE_IMPL(CodeTemplateScope.SERVER, "templates/server_BatchLoaderDelegateImpl.vm.java"), //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,76 @@ public interface CommonConfiguration {
*/
public boolean isAddRelayConnections();

/**
* An optional prefix to add to the classnames of the generated java classes for GraphQL types.
* The prefix is added at the beginning of the java classname, and must be compatible with java naming rules
* (no space, dot, comma, etc.)
*/
public String getTypePrefix();

/**
* An optional suffix to add to the classnames of the generated java classes for GraphQL types.
* The suffix is added at the end of the java classname, and must be compatible with java naming rules (no space,
* dot, comma, etc.)
*/
public String getTypeSuffix();

/**
* An optional prefix to add to the classnames of the generated java classes for GraphQL input objects.
* The prefix is added at the beginning of the java classname, and must be compatible with java naming rules
* (no space, dot, comma, etc.)
*/
public String getInputPrefix();

/**
* An optional suffix to add to the classnames of the generated java classes for GraphQL input objects.
* The suffix is added at the end of the java classname, and must be compatible with java naming rules (no space,
* dot, comma, etc.)
*/
public String getInputSuffix();

/**
* An optional prefix to add to the classnames of the generated java classes for GraphQL unions.
* The prefix is added at the beginning of the java classname, and must be compatible with java naming rules
* (no space, dot, comma, etc.)
*/
public String getUnionPrefix();

/**
* An optional suffix to add to the classnames of the generated java classes for GraphQL unions.
* The suffix is added at the end of the java classname, and must be compatible with java naming rules (no space,
* dot, comma, etc.)
*/
public String getUnionSuffix();

/**
* An optional prefix to add to the classnames of the generated java classes for GraphQL interfaces.
* The prefix is added at the beginning of the java classname, and must be compatible with java naming rules
* (no space, dot, comma, etc.)
*/
public String getInterfacePrefix();

/**
* An optional suffix to add to the classnames of the generated java classes for GraphQL interfaces.
* The suffix is added at the end of the java classname, and must be compatible with java naming rules (no space,
* dot, comma, etc.)
*/
public String getInterfaceSuffix();

/**
* An optional prefix to add to the classnames of the generated java classes for GraphQL enums.
* The prefix is added at the beginning of the java classname, and must be compatible with java naming rules
* (no space, dot, comma, etc.)
*/
public String getEnumPrefix();

/**
* An optional suffix to add to the classnames of the generated java classes for GraphQL enums.
* The suffix is added at the end of the java classname, and must be compatible with java naming rules (no space,
* dot, comma, etc.)
*/
public String getEnumSuffix();

/**
* This method is used only in {@link GeneratePojoConfiguration}.
*
Expand Down Expand Up @@ -164,6 +234,16 @@ public default void logCommonConfiguration() {
.map(entry -> String.format("%s=%s", entry.getKey(), entry.getValue()))
.collect(Collectors.joining(", "))
: ""));
logger.debug(" typePrefix: " + getTypePrefix());
logger.debug(" typeSuffix: " + getTypeSuffix());
logger.debug(" inputPrefix: " + getInputPrefix());
logger.debug(" inputSuffix: " + getInputSuffix());
logger.debug(" enumPrefix: " + getEnumPrefix());
logger.debug(" enumSuffix: " + getEnumSuffix());
logger.debug(" interfacePrefix: " + getInterfacePrefix());
logger.debug(" interfaceSuffix: " + getInterfaceSuffix());
logger.debug(" unionPrefix: " + getUnionPrefix());
logger.debug(" unionSuffix: " + getUnionSuffix());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ void addTypeAnnotationForClientMode(Type type) {
jsonSubTypes.append(",");
else
addSeparator = true;
jsonSubTypes.append(" @Type(value = ").append(t.getName()).append(".class, name = \"")
jsonSubTypes.append(" @Type(value = ").append(t.getJavaName()).append(".class, name = \"")
.append(t.getName()).append("\")");
}
jsonSubTypes.append(" })");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,29 @@ private int generateClientFiles() throws IOException {
logger.debug("Generating Spring auto-configuration generation");
i += generateSpringAutoConfigurationDeclaration();
}


logger.debug("Generating client side mapping from graphql type to java type");
i += generateClientTypeMapping();

return i;
}

/**
* Generate a class for mapping from graphql types to client java classes.
*
* @return
*/
private int generateClientTypeMapping() {
VelocityContext context = getVelocityContext();
context.put("types", generateCodeDocumentParser.getTypes());

generateOneFile(getJavaFile("GraphQLTypeMapping", false), "generating GraphQLTypeMapping", context,
resolveTemplate(CodeTemplate.TYPE_MAPPING));

return 1;
}

/**
* Generates the Spring auto-configuration file (META-INF/spring.factories), or update it to declare the
* SpringAutoConfiguration for this generation
Expand Down Expand Up @@ -568,7 +588,7 @@ int generateServerFiles() throws IOException {
}

for (BatchLoader batchLoader : generateCodeDocumentParser.batchLoaders) {
String name = "BatchLoaderDelegate" + batchLoader.getType().getClassSimpleName() + "Impl";
String name = "BatchLoaderDelegate" + batchLoader.getType().getName() + "Impl";
context.put("batchLoader", batchLoader);
logger.debug("Generating " + name);
ret += generateOneFile(getJavaFile(name, true), "generating " + name, context,
Expand Down Expand Up @@ -614,6 +634,56 @@ public boolean isAddRelayConnections() {
return configuration.isAddRelayConnections();
}

@Override
public String getTypePrefix() {
return configuration.getTypePrefix();
}

@Override
public String getTypeSuffix() {
return configuration.getTypeSuffix();
}

@Override
public String getInputPrefix() {
return configuration.getInputPrefix();
}

@Override
public String getInputSuffix() {
return configuration.getInputSuffix();
}

@Override
public String getUnionPrefix() {
return configuration.getUnionPrefix();
}

@Override
public String getUnionSuffix() {
return configuration.getUnionSuffix();
}

@Override
public String getInterfacePrefix() {
return configuration.getInterfacePrefix();
}

@Override
public String getInterfaceSuffix() {
return configuration.getInterfaceSuffix();
}

@Override
public String getEnumPrefix() {
return configuration.getEnumPrefix();
}

@Override
public String getEnumSuffix() {
return configuration.getEnumSuffix();
}

@Override
public String getResourceEncoding() {
return "UTF-8";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ default public String getJavaName() {
default public String getTargetFileName(String fileType) {
switch (fileType) {
case "executor":
return getJavaName() + "Executor";
return getName() + "Executor";
case "response":
return getJavaName() + "Response";
return getName() + "Response";
case "root response":
return getJavaName() + "RootResponse";
return getName() + "RootResponse";
default:
return getJavaName();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.graphql_java_generator.plugin.DocumentParser;
import com.graphql_java_generator.plugin.conf.CommonConfiguration;
Expand Down Expand Up @@ -86,10 +89,26 @@ public String getClassSimpleName() {
return getJavaName();
}

@Override
public String getJavaName() {
// Optionally add a prefix and/or suffix to the name
String name = Stream.of(getPrefix(), getName(), getSuffix())
.filter(Objects::nonNull).collect(Collectors.joining());

return GraphqlUtils.graphqlUtils.getJavaName(name);
}

protected String getPrefix() {
return "";
}
protected String getSuffix() {
return "";
}

/** {@inheritDoc} */
@Override
public String getCamelCaseName() {
return GraphqlUtils.graphqlUtils.getCamelCase(getClassSimpleName());
return GraphqlUtils.graphqlUtils.getCamelCase(getName());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ public DataFetchersDelegateImpl(Type type) {

@Override
public String getName() {
return "DataFetchersDelegate" + type.getClassSimpleName();
return "DataFetchersDelegate" + type.getName();
}
}
Loading