use of com.graphql_java_generator.plugin.language.impl.ObjectType in project graphql-maven-plugin-project by graphql-java-generator.
the class AddRelayConnections method addPageInfoType.
/**
* Adds the <I>PageInfo</I> type, as defined in the <A HREF="https://relay.dev/graphql/connections.htm">Relay
* Connection specification</A>. If a <I>PageInfo</I> type already exists in the schema, it is checked to be
* compliant to this specification. If not, an exception is thrown.
*
* @throws RuntimeException
* Thrown if a <I>PageInfo</I> type already exists, but is not compliant with the Relay Connection
* specification
*/
void addPageInfoType() {
final String PAGE_INFO = "PageInfo";
Type o = documentParser.getType(PAGE_INFO, false);
if (o == null) {
// PageInfo is not defined in the GraphQL source schema. Let's add it.
ObjectType pageInfo = new ObjectType(PAGE_INFO, configuration, documentParser);
// Adding the PageInfo's fields
pageInfo.getFields().add(FieldImpl.builder().name("hasNextPage").owningType(pageInfo).documentParser(documentParser).fieldTypeAST(//
FieldTypeAST.builder().graphQLTypeSimpleName("Boolean").mandatory(true).build()).build());
pageInfo.getFields().add(FieldImpl.builder().name("hasPreviousPage").owningType(pageInfo).documentParser(documentParser).fieldTypeAST(//
FieldTypeAST.builder().graphQLTypeSimpleName("Boolean").mandatory(true).build()).build());
pageInfo.getFields().add(FieldImpl.builder().name("startCursor").owningType(pageInfo).documentParser(documentParser).fieldTypeAST(//
FieldTypeAST.builder().graphQLTypeSimpleName("String").mandatory(true).build()).build());
pageInfo.getFields().add(FieldImpl.builder().name("endCursor").owningType(pageInfo).documentParser(documentParser).fieldTypeAST(//
FieldTypeAST.builder().graphQLTypeSimpleName("String").mandatory(true).build()).build());
//
documentParser.getObjectTypes().add(pageInfo);
documentParser.getTypes().put(PAGE_INFO, pageInfo);
} else if (!(o instanceof ObjectType)) {
throw new RuntimeException("A " + PAGE_INFO + " item already exists in the GraphQL schema, but it isn't a GraphQL type");
} else {
// PageInfo is defined in the GraphQL source schema. Let's check that it is compliant to the relay
// specification.
ObjectType pageInfo = (ObjectType) o;
if (pageInfo.getMemberOfUnions().size() != 0) {
throw new RuntimeException("The " + PAGE_INFO + " type already exists, but is not compliant with the Relay specification (member of unions)");
}
if (pageInfo.getFields().size() < 4) {
throw new RuntimeException("The " + PAGE_INFO + " type already exists, but is not compliant with the Relay specification (it should contain exactly at least four fields)");
}
checkField(pageInfo, "hasNextPage", false, false, true, false, "Boolean", 0);
checkField(pageInfo, "hasPreviousPage", false, false, true, false, "Boolean", 0);
checkField(pageInfo, "startCursor", false, false, true, false, "String", 0);
checkField(pageInfo, "endCursor", false, false, true, false, "String", 0);
}
}
use of com.graphql_java_generator.plugin.language.impl.ObjectType in project graphql-maven-plugin-project by graphql-java-generator.
the class DocumentParser method parseOneDocument.
/**
* Generates the target classes for the given GraphQL schema definition
*
* @param document
*/
public void parseOneDocument(Document document) {
// List of all the names of the query types. There should be only one. But we're ready for more (for instance if
// several schema files have been merged)
List<String> queryObjectNames = new ArrayList<>();
// List of all the names of the mutation types. There should be only one. But we're ready for more (for instance
// if several schema files have been merged)
List<String> mutationObjectNames = new ArrayList<>();
// List of all the names of the subscription types. There should be only one. But we're ready for more (for
// instance if several schema files have been merged)
List<String> subscriptionObjectNames = new ArrayList<>();
// The Directives must be read first, as they may be found on almost any kind of definition in the GraphQL
// schema
document.getDefinitions().stream().filter(n -> (n instanceof DirectiveDefinition)).forEach(node -> directives.add(readDirectiveDefinition((DirectiveDefinition) node)));
// Looks for a schema definitions, to list the defined queries, mutations and subscriptions (should be only one
// of each), but we're ready for more. (for instance if several schema files have been merged)
logger.debug("Looking for schema definition");
for (Definition<?> node : document.getDefinitions()) {
if (node instanceof SchemaDefinition) {
readSchemaDefinition((SchemaDefinition) node, queryObjectNames, mutationObjectNames, subscriptionObjectNames);
}
// if
}
// for
logger.debug("Reading node definitions");
for (Definition<?> node : document.getDefinitions()) {
// directive
if (node instanceof DirectiveDefinition) {
// Directives are read latter
} else // enum
if (node instanceof EnumTypeDefinition) {
enumTypes.add(readEnumType((EnumTypeDefinition) node));
} else // input object
if (node instanceof InputObjectTypeDefinition) {
objectTypes.add(readInputObjectType((InputObjectTypeDefinition) node));
} else // interface
if (node instanceof InterfaceTypeDefinition) {
interfaceTypes.add(readInterfaceType((InterfaceTypeDefinition) node));
} else // extend object
if (node instanceof ObjectTypeExtensionDefinition) {
// ObjectTypeExtensionDefinition is a subclass of ObjectTypeDefinition, so we need to check it first.
//
// No action here: we'll manage all the object extensions once all object definitions have been read
objectTypeExtensionDefinitions.add((ObjectTypeExtensionDefinition) node);
} else // object
if (node instanceof ObjectTypeDefinition) {
// Let's check what kind of ObjectDefinition we have
String name = ((ObjectTypeDefinition) node).getName();
if (queryObjectNames.contains(name) || DEFAULT_QUERY_NAME.equals(name)) {
// We first read the object type, that'll go to the main package
ObjectType o = readObjectTypeDefinition((ObjectTypeDefinition) node);
o.setRequestType("query");
objectTypes.add(o);
// Then we read the query, that'll go in the util subpackage: its imports are different
if (queryType != null) {
throw new RuntimeException("Error while reading the query '" + ((ObjectTypeDefinition) node).getName() + "'. A Query root operation has already been read, with name'" + queryType.getName() + "'");
}
queryType = o;
} else if (mutationObjectNames.contains(name) || DEFAULT_MUTATION_NAME.equals(name)) {
// We first read the object type, that'll go to the main package
ObjectType o = readObjectTypeDefinition((ObjectTypeDefinition) node);
o.setRequestType("mutation");
objectTypes.add(o);
// Then we read the mutation, that'll go in the util subpackage: its imports are different
if (mutationType != null) {
throw new RuntimeException("Error while reading the mutation '" + ((ObjectTypeDefinition) node).getName() + "'. A Mutation root operation has already been read, with name'" + mutationType.getName() + "'");
}
mutationType = o;
} else if (subscriptionObjectNames.contains(name) || DEFAULT_SUBSCRIPTION_NAME.equals(name)) {
// We first read the object type, that'll go to the main package
ObjectType o = readObjectTypeDefinition((ObjectTypeDefinition) node);
o.setRequestType("subscription");
objectTypes.add(o);
// Then we read the subscription, that'll go in the util subpackage: its imports are different
if (subscriptionType != null) {
throw new RuntimeException("Error while reading the subscription '" + ((ObjectTypeDefinition) node).getName() + "'. A Subscription root operation has already been read, with name'" + subscriptionType.getName() + "'");
}
subscriptionType = o;
} else {
objectTypes.add(readObjectTypeDefinition((ObjectTypeDefinition) node));
}
} else // scalar extension
if (node instanceof ScalarTypeExtensionDefinition) {
readScalarExtensionType((ScalarTypeExtensionDefinition) node);
} else // scalar
if (node instanceof ScalarTypeDefinition) {
// Custom scalars implementation must be provided by the configuration. We just check that it's OK.
readCustomScalarType((ScalarTypeDefinition) node);
} else // schema
if (node instanceof SchemaDefinition) {
// No action, we already parsed it
} else // union
if (node instanceof UnionTypeDefinition) {
// Unions are read latter, once all GraphQL types have been parsed
} else {
logger.warn("Non managed node type: " + node.getClass().getName());
}
}
// for
// Once all Types have been properly read, we can read the union types
logger.debug("Reading union definitions");
document.getDefinitions().stream().filter(n -> (n instanceof UnionTypeDefinition)).forEach(n -> unionTypes.add(readUnionType((UnionTypeDefinition) n)));
}
use of com.graphql_java_generator.plugin.language.impl.ObjectType in project graphql-maven-plugin-project by graphql-java-generator.
the class GenerateCodeDocumentParser method addTypeAnnotationForClientMode.
/**
* This method add the needed annotation(s) to the given type, when in client mode
*
* @param type
*/
void addTypeAnnotationForClientMode(Type type) {
if (type instanceof InterfaceType || type instanceof UnionType) {
if (configuration.isGenerateJacksonAnnotations()) {
type.addImport(configuration.getPackageName(), JsonTypeInfo.class.getName());
type.addImport(configuration.getPackageName(), JsonTypeInfo.Id.class.getName());
type.addAnnotation("@JsonTypeInfo(use = Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = \"__typename\", visible = true)");
// jsonSubTypes annotation looks like this:
// @JsonSubTypes({ @Type(value = Droid.class, name = "Droid"), @Type(value = Human.class, name =
// "Human") })
StringBuffer jsonSubTypes = new StringBuffer();
type.addImport(configuration.getPackageName(), JsonSubTypes.class.getName());
type.addImport(configuration.getPackageName(), JsonSubTypes.Type.class.getName());
jsonSubTypes.append("@JsonSubTypes({");
boolean addSeparator = false;
List<ObjectType> types;
if (type instanceof InterfaceType)
types = ((InterfaceType) type).getImplementingTypes();
else
types = ((UnionType) type).getMemberTypes();
for (ObjectType t : types) {
// No separator for the first iteration
if (addSeparator)
jsonSubTypes.append(",");
else
addSeparator = true;
jsonSubTypes.append(" @Type(value = ").append(t.getName()).append(".class, name = \"").append(t.getName()).append("\")");
}
jsonSubTypes.append(" })");
type.addAnnotation(jsonSubTypes.toString());
}
}
// query/mutation/subscription
if (type instanceof ObjectType && ((ObjectType) type).getRequestType() != null) {
type.addImport(configuration.getPackageName(), GraphQLQuery.class.getName());
type.addImport(configuration.getPackageName(), RequestType.class.getName());
type.addAnnotation("@GraphQLQuery(name = \"" + type.getName() + "\", type = RequestType." + ((ObjectType) type).getRequestType() + ")");
}
// Let's add the annotations, that are common to both the client and the server mode
addTypeAnnotationForBothClientAndServerMode(type);
}
use of com.graphql_java_generator.plugin.language.impl.ObjectType in project graphql-maven-plugin-project by graphql-java-generator.
the class GenerateCodeDocumentParser method addIntrospectionCapabilities.
/**
* Add introspection capabilities: the __schema and __type query into a dedicated __IntrospectionQuery, and the
* __typename into each GraphQL object.<BR/>
* Note: the introspection schema has already been parsed, as it is added by {@link ResourceSchemaStringProvider} in
* the documents list
*/
void addIntrospectionCapabilities() {
// No action in server mode: everything is handled by graphql-java
if (configuration.getMode().equals(PluginMode.client)) {
logger.debug("Adding introspection capability");
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (queryType == null) {
logger.debug("The source schema contains no query: creating an empty query type");
// There was no query. We need to create one. It will contain only the Introspection Query
queryType = new ObjectType(DEFAULT_QUERY_NAME, configuration, this);
queryType.setName(INTROSPECTION_QUERY);
queryType.setRequestType("query");
// Let's first add the regular object that'll receive the server response (in the default package)
getObjectTypes().add(queryType);
types.put(queryType.getName(), queryType);
}
// We also need to add the relevant fields into the regular object that matches the query.
Type objectQuery = getType(queryType.getName());
objectQuery.getFields().add(get__SchemaField(objectQuery));
objectQuery.getFields().add(get__TypeField(objectQuery));
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Second step: add the __datatype field into every GraphQL type (out of input types)
// That is : in all regular object types and interfaces.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
logger.debug("Adding __typename to each object");
for (ObjectType type : getObjectTypes()) {
if (!type.isInputType()) {
type.getFields().add(FieldImpl.builder().documentParser(this).name("__typename").fieldTypeAST(FieldTypeAST.builder().graphQLTypeSimpleName("String").mandatory(false).build()).owningType(type).build());
}
}
logger.debug("Adding __typename to each interface");
for (InterfaceType type : interfaceTypes) {
type.getFields().add(FieldImpl.builder().documentParser(this).name("__typename").fieldTypeAST(FieldTypeAST.builder().graphQLTypeSimpleName("String").mandatory(false).build()).owningType(type).build());
}
}
}
use of com.graphql_java_generator.plugin.language.impl.ObjectType in project graphql-maven-plugin-project by graphql-java-generator.
the class GenerateCodeDocumentParser method initRelations.
/**
* Reads all the GraphQl objects, interfaces, union... that have been read from the GraphQL schema, and list all the
* relations between Server objects (that is: all objects out of the Query/Mutation/Subscription types and the input
* types). The found relations are stored, to be reused during the code generation.<BR/>
* These relations are important for the server mode of the plugin, to generate the proper JPA annotations.
*/
void initRelations() {
for (ObjectType type : getObjectTypes()) {
// We initiate the relations only for regular objects (not query/mutation/subscription)
if (type.getRequestType() == null) {
if (!type.isInputType()) {
for (Field field : type.getFields()) {
if (field.getType() instanceof ObjectType) {
RelationType relType = field.getFieldTypeAST().getListDepth() > 0 ? RelationType.OneToMany : RelationType.ManyToOne;
RelationImpl relation = new RelationImpl(type, field, relType);
//
((FieldImpl) field).setRelation(relation);
relations.add(relation);
}
// if (instanceof ObjectType)
}
// if (!type.isInputType())
}
// for (field)
}
// if (type.getRequestType()== null)
}
// for (type)
}
Aggregations