Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
*
*/
package com.graphql_java_generator.util;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.graphql_java_generator.annotation.GraphQLNonScalar;
import com.graphql_java_generator.annotation.GraphQLScalar;
import com.graphql_java_generator.customscalars.CustomScalar;
import com.graphql_java_generator.customscalars.CustomScalarRegistryImpl;
import com.graphql_java_generator.exception.GraphQLRequestPreparationException;
import graphql.language.ArrayValue;
import graphql.language.BooleanValue;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.NullValue;
import graphql.language.ObjectField;
import graphql.language.ObjectValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.GraphQLScalarType;
/**
* @author etienne-sf
*/
@Component
public class GraphqlUtils {
/** Logger for this class */
private static Logger logger = LoggerFactory.getLogger(GraphqlUtils.class);
/** This singleton is usable in default method, within interfaces */
public static GraphqlUtils graphqlUtils = new GraphqlUtils();
Pattern graphqlNamePattern = Pattern.compile("^[_A-Za-z][_0-9A-Za-z]*$");
/**
* The list of Java keywords. This keyword may not be used as java identifier, within java code (for instance for
* class name, field name...).
* If a GraphQL identifier is one of these keyword, it will be prefixed by {@link #JAVA_KEYWORD_PREFIX} in the
* generated code.
*/
private List javaKeywords = new ArrayList<>();
/**
* The runtime properties, as they are in the graphql-java-runtime.properties file. This includes the version of the
* runtime, that is used to check that the runtime's version is the same as the Maven or Gradle plugin's version
*/
private Properties properties;
final static String PROPERTIES_FILE = "graphql-java-runtime.properties";
final static String PROP_RUNTIME_VERSION = "graphql-java-runtime.version";
public static Character JAVA_KEYWORD_PREFIX = '_';
public GraphqlUtils() {
// List all java reserved keywords.
javaKeywords.add("abstract");
javaKeywords.add("assert");
javaKeywords.add("boolean");
javaKeywords.add("break");
javaKeywords.add("byte");
javaKeywords.add("case");
javaKeywords.add("catch");
javaKeywords.add("char");
javaKeywords.add("class");
javaKeywords.add("const");
javaKeywords.add("continue");
javaKeywords.add("default");
javaKeywords.add("do");
javaKeywords.add("double");
javaKeywords.add("else");
javaKeywords.add("enum");
javaKeywords.add("extends");
javaKeywords.add("final");
javaKeywords.add("finally");
javaKeywords.add("float");
javaKeywords.add("for");
javaKeywords.add("goto");
javaKeywords.add("if");
javaKeywords.add("implements");
javaKeywords.add("import");
javaKeywords.add("instanceof");
javaKeywords.add("int");
javaKeywords.add("interface");
javaKeywords.add("long");
javaKeywords.add("native");
javaKeywords.add("new");
javaKeywords.add("package");
javaKeywords.add("private");
javaKeywords.add("protected");
javaKeywords.add("public");
javaKeywords.add("return");
javaKeywords.add("short");
javaKeywords.add("static");
javaKeywords.add("strictfp");
javaKeywords.add("super");
javaKeywords.add("switch");
javaKeywords.add("synchronized");
javaKeywords.add("this");
javaKeywords.add("throw");
javaKeywords.add("throws");
javaKeywords.add("transient");
javaKeywords.add("try");
javaKeywords.add("void");
javaKeywords.add("volatile");
javaKeywords.add("while");
}
/**
* Returns the version of the runtime, that is used to check that the runtime's version is the same as the Maven or
* Gradle plugin's version.
*/
public String getRuntimeVersion() {
return getProperties().getProperty(PROP_RUNTIME_VERSION);
}
/** Loads the runtime properties file, from the graphql-java-runtime.properties file. */
private Properties getProperties() {
if (properties == null) {
properties = new Properties();
try {
properties.load(getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE));
} catch (IOException e) {
String msg = "Error while reading the '" + PROPERTIES_FILE + "' properties file: " + e.getMessage();
logger.error(msg);
throw new RuntimeException(msg, e);
}
}
return properties;
}
/**
* Convert the given name, to a camel case name. Currenly very simple : it puts the first character in lower case.
*
* @return
*/
public String getCamelCase(String name) {
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
/**
* Convert the given name, which is supposed to be in camel case (for instance: thisIsCamelCase) to a pascal case
* string (for instance: ThisIsCamelCase).
*
* @return
*/
public String getPascalCase(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
/**
* Transform an {@link Iterable} (which can be a {@link List}), into a {@link List} of items of the same type. It's
* usefull to transform the native type from Spring Data repositories (which needs concrete class to map into) into
* the list of relevant GraphQL interface
*
* @param
* @param iterable
* @return
*/
public List iterableToList(Iterable iterable) {
List ret = new ArrayList();
for (I i : iterable) {
ret.add(i);
}
return ret;
}
/**
* Transform an {@link Iterable} (which can be a {@link List}) of a concrete class, into a {@link List} of the I
* interface or superclass. It's usefull to transform the native type from Spring Data repositories (which needs
* concrete class to map into) into the list of relevant GraphQL interface
*
* @param
* @param iterable
* @return
*/
public List iterableConcreteClassToListInterface(Iterable extends I> iterable) {
List ret = new ArrayList();
for (I i : iterable) {
ret.add(i);
}
return ret;
}
/**
* Transform an {@link Optional}, as returned by Spring Data repositories, into a standard Java, which is null if
* there is no value.
*
* @param optional
* @return
*/
public T optionalToObject(Optional optional) {
return optional.isPresent() ? optional.get() : null;
}
/**
* Retrieves the class of the fieldName field of the owningClass class.
*
* @param owningClass
* @param fieldName
* @param returnIsMandatory
* If true, a {@link GraphQLRequestPreparationException} is thrown if the field is not found.
* @return The class of the field. Or null of the field doesn't exist, and returnIdMandatory is false
* @throws GraphQLRequestPreparationException
*/
public Class> getFieldType(Class> owningClass, String fieldName, boolean returnIsMandatory)
throws GraphQLRequestPreparationException {
if (owningClass.isInterface()) {
// We try to get the class of this getter of the field
try {
Method method = owningClass.getDeclaredMethod("get" + graphqlUtils.getPascalCase(fieldName));
// We must manage the type erasure for list. So we use the GraphQL annotations to retrieve types.
GraphQLNonScalar graphQLNonScalar = method.getAnnotation(GraphQLNonScalar.class);
GraphQLScalar graphQLScalar = method.getAnnotation(GraphQLScalar.class);
if (graphQLNonScalar != null)
return graphQLNonScalar.javaClass();
else if (graphQLScalar != null)
return graphQLScalar.javaClass();
else
throw new GraphQLRequestPreparationException("Error while looking for the getter for the field '"
+ fieldName + "' in the interface '" + owningClass.getName()
+ "': this method should have one of these annotations: GraphQLNonScalar or GraphQLScalar ");
} catch (NoSuchMethodException e) {
// Hum, the field doesn't exist.
if (!returnIsMandatory)
return null;
else
throw new GraphQLRequestPreparationException("Error while looking for the getter for the field '"
+ fieldName + "' in the class '" + owningClass.getName() + "'", e);
} catch (SecurityException e) {
throw new GraphQLRequestPreparationException("Error while looking for the getter for the field '"
+ fieldName + "' in the class '" + owningClass.getName() + "'", e);
}
} else {
// We try to get the class of this field
try {
Field field = owningClass.getDeclaredField(graphqlUtils.getJavaName(fieldName));
// We must manage the type erasure for list. So we use the GraphQL annotations to retrieve types.
GraphQLNonScalar graphQLNonScalar = field.getAnnotation(GraphQLNonScalar.class);
GraphQLScalar graphQLScalar = field.getAnnotation(GraphQLScalar.class);
if (graphQLNonScalar != null)
return graphQLNonScalar.javaClass();
else if (graphQLScalar != null)
return graphQLScalar.javaClass();
else
throw new GraphQLRequestPreparationException("Error while looking for the the field '" + fieldName
+ "' in the class '" + owningClass.getName()
+ "': this field should have one of these annotations: GraphQLNonScalar or GraphQLScalar ");
} catch (NoSuchFieldException e) {
// Hum, the field doesn't exist.
if (!returnIsMandatory)
return null;
else
throw new GraphQLRequestPreparationException("Error while looking for the the field '" + fieldName
+ "' in the class '" + owningClass.getName() + "'", e);
} catch (SecurityException e) {
throw new GraphQLRequestPreparationException("Error while looking for the the field '" + fieldName
+ "' in the class '" + owningClass.getName() + "'", e);
}
}
}
/**
* This method returns a GraphQL argument into the relevant Java object, within a data fetcher, from what has been
* parsed by the graphql-java engine from the incoming JSON request
*
* @param
* The class expected to be returned
* @param jsonParsedValue
* The value, read from the JSON in the GraphQL request. Only the part of the JSON map, related to the
* expected class is sent. It can be:
*
*
A {@link Map}. This map will be transformed into an input object, as defined in the GraphQL
* schema, from the Map that has been read from the JSON object sent to the server.
*
A {@link List}. In this case, returns a list of instances of the given clazz type.
*
Otherwise, the value is a scalar. At this stage, Custom Scalars have already been transformed into
* the relevant Java Type. So it must be a standard scalar. It is then mapped to the asked java type
*
* @param graphQLTypeName
* The name of the GraphQL type, as defined in the GraphQL schema. This can be guessed from the given
* class for input types and objects, but not for scalars. So it must be provided.
* @param javaTypeForIDType
* Value of the plugin parameter of the same name. This is necessary to properly manage fields of the ID
* GraphQL type, which must be transformed to this java type. This is useful only when mapping into input
* types.
* @param clazz
* The class of the expected type. A new instance of this type will be returned, with its fields having
* been set by this method from the value in the map
* @return An instance of the expected class. If the map is null, null is returned. Of the map is empty, anew
* instance is returned, with all its fields are left empty
*/
@SuppressWarnings("unchecked")
public Object getArgument(Object jsonParsedValue, String graphQLTypeName, String javaTypeForIDType,
Class> clazz) {
if (jsonParsedValue == null) {
return null;
} else if (jsonParsedValue instanceof List>) {
// We've a list. Let's loop inside its items
List