@graphql-codegen/java-apollo-android 2.2.13 → 2.3.0-alpha-29eb1293b.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/cjs/base-java-visitor.js +114 -0
  2. package/cjs/custom-type-class.js +69 -0
  3. package/cjs/field-arguments.js +36 -0
  4. package/cjs/file-type.js +10 -0
  5. package/cjs/imports.js +45 -0
  6. package/cjs/index.js +5 -0
  7. package/cjs/input-type-visitor.js +187 -0
  8. package/cjs/operation-visitor.js +780 -0
  9. package/cjs/package.json +1 -0
  10. package/cjs/plugin.js +48 -0
  11. package/cjs/preset.js +95 -0
  12. package/cjs/types.js +2 -0
  13. package/cjs/visitor-config.js +2 -0
  14. package/esm/base-java-visitor.js +110 -0
  15. package/esm/custom-type-class.js +65 -0
  16. package/esm/field-arguments.js +32 -0
  17. package/esm/file-type.js +7 -0
  18. package/esm/imports.js +42 -0
  19. package/esm/index.js +2 -0
  20. package/esm/input-type-visitor.js +183 -0
  21. package/{index.mjs → esm/operation-visitor.js} +8 -565
  22. package/esm/plugin.js +44 -0
  23. package/esm/preset.js +92 -0
  24. package/esm/types.js +1 -0
  25. package/esm/visitor-config.js +1 -0
  26. package/package.json +23 -16
  27. package/{base-java-visitor.d.ts → typings/base-java-visitor.d.ts} +3 -3
  28. package/{custom-type-class.d.ts → typings/custom-type-class.d.ts} +3 -3
  29. package/{field-arguments.d.ts → typings/field-arguments.d.ts} +1 -1
  30. package/{file-type.d.ts → typings/file-type.d.ts} +0 -0
  31. package/{imports.d.ts → typings/imports.d.ts} +0 -0
  32. package/typings/index.d.ts +2 -0
  33. package/{input-type-visitor.d.ts → typings/input-type-visitor.d.ts} +3 -3
  34. package/{operation-visitor.d.ts → typings/operation-visitor.d.ts} +3 -3
  35. package/{plugin.d.ts → typings/plugin.d.ts} +1 -1
  36. package/{preset.d.ts → typings/preset.d.ts} +0 -0
  37. package/{types.d.ts → typings/types.d.ts} +0 -0
  38. package/{visitor-config.d.ts → typings/visitor-config.d.ts} +0 -0
  39. package/index.d.ts +0 -2
  40. package/index.js +0 -1339
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
package/cjs/plugin.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.plugin = void 0;
4
+ const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
5
+ const graphql_1 = require("graphql");
6
+ const input_type_visitor_js_1 = require("./input-type-visitor.js");
7
+ const operation_visitor_js_1 = require("./operation-visitor.js");
8
+ const file_type_js_1 = require("./file-type.js");
9
+ const custom_type_class_js_1 = require("./custom-type-class.js");
10
+ const plugin = (schema, documents, config) => {
11
+ const allAst = (0, graphql_1.concatAST)(documents.map(v => v.document));
12
+ const allFragments = [
13
+ ...allAst.definitions.filter(d => d.kind === graphql_1.Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
14
+ node: fragmentDef,
15
+ name: fragmentDef.name.value,
16
+ onType: fragmentDef.typeCondition.name.value,
17
+ isExternal: false,
18
+ })),
19
+ ...(config.externalFragments || []),
20
+ ];
21
+ let visitor;
22
+ switch (config.fileType) {
23
+ case file_type_js_1.FileType.FRAGMENT:
24
+ case file_type_js_1.FileType.OPERATION: {
25
+ visitor = new operation_visitor_js_1.OperationVisitor(schema, config, allFragments);
26
+ break;
27
+ }
28
+ case file_type_js_1.FileType.INPUT_TYPE: {
29
+ visitor = new input_type_visitor_js_1.InputTypeVisitor(schema, config);
30
+ break;
31
+ }
32
+ case file_type_js_1.FileType.CUSTOM_TYPES: {
33
+ visitor = new custom_type_class_js_1.CustomTypeClassVisitor(schema, config);
34
+ break;
35
+ }
36
+ }
37
+ if (!visitor) {
38
+ return { content: '' };
39
+ }
40
+ const visitResult = (0, plugin_helpers_1.oldVisit)(allAst, visitor);
41
+ const additionalContent = visitor.additionalContent();
42
+ const imports = visitor.getImports();
43
+ return {
44
+ prepend: [`package ${visitor.getPackage()};\n`, ...imports],
45
+ content: '\n' + [...visitResult.definitions.filter(a => a && typeof a === 'string'), additionalContent].join('\n'),
46
+ };
47
+ };
48
+ exports.plugin = plugin;
package/cjs/preset.js ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preset = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const path_1 = require("path");
6
+ const file_type_js_1 = require("./file-type.js");
7
+ const change_case_all_1 = require("change-case-all");
8
+ const packageNameToDirectory = (packageName) => {
9
+ return `./${packageName.split('.').join('/')}/`;
10
+ };
11
+ exports.preset = {
12
+ buildGeneratesSection: options => {
13
+ const outDir = options.baseOutputDir;
14
+ const inputTypesAst = [];
15
+ (0, graphql_1.visit)(options.schema, {
16
+ InputObjectTypeDefinition: {
17
+ enter(node) {
18
+ inputTypesAst.push(node);
19
+ },
20
+ },
21
+ });
22
+ const inputTypesDocumentNode = { kind: graphql_1.Kind.DOCUMENT, definitions: inputTypesAst };
23
+ const allAst = (0, graphql_1.concatAST)(options.documents.map(v => v.document));
24
+ const operationsAst = allAst.definitions.filter(d => d.kind === graphql_1.Kind.OPERATION_DEFINITION);
25
+ const fragments = allAst.definitions.filter(d => d.kind === graphql_1.Kind.FRAGMENT_DEFINITION);
26
+ const externalFragments = fragments.map(frag => ({
27
+ isExternal: true,
28
+ importFrom: frag.name.value,
29
+ name: frag.name.value,
30
+ onType: frag.typeCondition.name.value,
31
+ node: frag,
32
+ }));
33
+ return [
34
+ {
35
+ filename: (0, path_1.join)(outDir, packageNameToDirectory(options.config.typePackage), 'CustomType.java'),
36
+ plugins: options.plugins,
37
+ pluginMap: options.pluginMap,
38
+ config: {
39
+ ...options.config,
40
+ fileType: file_type_js_1.FileType.CUSTOM_TYPES,
41
+ },
42
+ schema: options.schema,
43
+ documents: [],
44
+ },
45
+ ...inputTypesDocumentNode.definitions.map((ast) => {
46
+ const document = { kind: graphql_1.Kind.DOCUMENT, definitions: [ast] };
47
+ return {
48
+ filename: (0, path_1.join)(outDir, packageNameToDirectory(options.config.typePackage), ast.name.value + '.java'),
49
+ plugins: options.plugins,
50
+ pluginMap: options.pluginMap,
51
+ config: {
52
+ ...options.config,
53
+ fileType: file_type_js_1.FileType.INPUT_TYPE,
54
+ skipDocumentsValidation: true,
55
+ },
56
+ schema: options.schema,
57
+ documents: [{ document, location: '' }],
58
+ };
59
+ }),
60
+ ...operationsAst.map((ast) => {
61
+ const fileName = ast.name.value.toLowerCase().endsWith(ast.operation)
62
+ ? ast.name.value
63
+ : `${ast.name.value}${(0, change_case_all_1.pascalCase)(ast.operation)}`;
64
+ const document = { kind: graphql_1.Kind.DOCUMENT, definitions: [ast] };
65
+ return {
66
+ filename: (0, path_1.join)(outDir, packageNameToDirectory(options.config.package), fileName + '.java'),
67
+ plugins: options.plugins,
68
+ pluginMap: options.pluginMap,
69
+ config: {
70
+ ...options.config,
71
+ fileType: file_type_js_1.FileType.OPERATION,
72
+ externalFragments,
73
+ },
74
+ schema: options.schema,
75
+ documents: [{ document, location: '' }],
76
+ };
77
+ }),
78
+ ...fragments.map((ast) => {
79
+ const document = { kind: graphql_1.Kind.DOCUMENT, definitions: [ast] };
80
+ return {
81
+ filename: (0, path_1.join)(outDir, packageNameToDirectory(options.config.fragmentPackage), ast.name.value + '.java'),
82
+ plugins: options.plugins,
83
+ pluginMap: options.pluginMap,
84
+ config: {
85
+ ...options.config,
86
+ fileType: file_type_js_1.FileType.FRAGMENT,
87
+ externalFragments,
88
+ },
89
+ schema: options.schema,
90
+ documents: [{ document, location: '' }],
91
+ };
92
+ }),
93
+ ];
94
+ },
95
+ };
package/cjs/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,110 @@
1
+ import { Imports } from './imports.js';
2
+ import { BaseVisitor, getBaseTypeNode, buildScalars } from '@graphql-codegen/visitor-plugin-common';
3
+ import { getBaseType } from '@graphql-codegen/plugin-helpers';
4
+ import { JAVA_SCALARS } from '@graphql-codegen/java-common';
5
+ import { isScalarType, isInputObjectType, Kind, isNonNullType, isListType, GraphQLObjectType, } from 'graphql';
6
+ export const SCALAR_TO_WRITER_METHOD = {
7
+ ID: 'writeString',
8
+ String: 'writeString',
9
+ Int: 'writeInt',
10
+ Boolean: 'writeBoolean',
11
+ Float: 'writeDouble',
12
+ };
13
+ function isTypeNode(type) {
14
+ return type && !!type.kind;
15
+ }
16
+ export class BaseJavaVisitor extends BaseVisitor {
17
+ constructor(_schema, rawConfig, additionalConfig) {
18
+ super(rawConfig, {
19
+ ...additionalConfig,
20
+ scalars: buildScalars(_schema, { ID: 'String' }, JAVA_SCALARS),
21
+ });
22
+ this._schema = _schema;
23
+ this._imports = new Set();
24
+ }
25
+ getPackage() {
26
+ return '';
27
+ }
28
+ additionalContent() {
29
+ return '';
30
+ }
31
+ getImports() {
32
+ return Array.from(this._imports).map(imp => `import ${imp};`);
33
+ }
34
+ getImplementingTypes(node) {
35
+ const allTypesMap = this._schema.getTypeMap();
36
+ const implementingTypes = [];
37
+ for (const graphqlType of Object.values(allTypesMap)) {
38
+ if (graphqlType instanceof GraphQLObjectType) {
39
+ const allInterfaces = graphqlType.getInterfaces();
40
+ if (allInterfaces.find(int => int.name === node.name)) {
41
+ implementingTypes.push(graphqlType.name);
42
+ }
43
+ }
44
+ }
45
+ return implementingTypes;
46
+ }
47
+ transformType(type) {
48
+ let schemaType;
49
+ let isNonNull;
50
+ if (isTypeNode(type)) {
51
+ const baseTypeNode = getBaseTypeNode(type);
52
+ schemaType = this._schema.getType(baseTypeNode.name.value);
53
+ isNonNull = type.kind === Kind.NON_NULL_TYPE;
54
+ }
55
+ else {
56
+ schemaType = this._schema.getType(getBaseType(type).name);
57
+ isNonNull = isNonNullType(type);
58
+ }
59
+ const javaType = this.getJavaClass(schemaType);
60
+ const annotation = isNonNull ? 'Nonnull' : 'Nullable';
61
+ const typeToUse = isTypeNode(type)
62
+ ? this.getListTypeNodeWrapped(javaType, type)
63
+ : this.getListTypeWrapped(javaType, type);
64
+ return {
65
+ baseType: schemaType.name,
66
+ javaType,
67
+ isNonNull,
68
+ annotation,
69
+ typeToUse,
70
+ };
71
+ }
72
+ // Replaces a GraphQL type with a Java class
73
+ getJavaClass(schemaType) {
74
+ let typeToUse = schemaType.name;
75
+ if (isScalarType(schemaType)) {
76
+ const scalar = this.scalars[schemaType.name] || 'Object';
77
+ if (Imports[scalar]) {
78
+ this._imports.add(Imports[scalar]);
79
+ }
80
+ typeToUse = scalar;
81
+ }
82
+ else if (isInputObjectType(schemaType)) {
83
+ // Make sure to import it if it's in use
84
+ this._imports.add(`${this.config.typePackage}.${schemaType.name}`);
85
+ }
86
+ return typeToUse;
87
+ }
88
+ getListTypeWrapped(toWrap, type) {
89
+ if (isNonNullType(type)) {
90
+ return this.getListTypeWrapped(toWrap, type.ofType);
91
+ }
92
+ if (isListType(type)) {
93
+ const child = this.getListTypeWrapped(toWrap, type.ofType);
94
+ this._imports.add(Imports.List);
95
+ return `List<${child}>`;
96
+ }
97
+ return toWrap;
98
+ }
99
+ getListTypeNodeWrapped(toWrap, type) {
100
+ if (type.kind === Kind.NON_NULL_TYPE) {
101
+ return this.getListTypeNodeWrapped(toWrap, type.type);
102
+ }
103
+ if (type.kind === Kind.LIST_TYPE) {
104
+ const child = this.getListTypeNodeWrapped(toWrap, type.type);
105
+ this._imports.add(Imports.List);
106
+ return `List<${child}>`;
107
+ }
108
+ return toWrap;
109
+ }
110
+ }
@@ -0,0 +1,65 @@
1
+ import { isScalarType } from 'graphql';
2
+ import { BaseJavaVisitor } from './base-java-visitor.js';
3
+ import { indentMultiline } from '@graphql-codegen/visitor-plugin-common';
4
+ import { Imports } from './imports.js';
5
+ import { JavaDeclarationBlock } from '@graphql-codegen/java-common';
6
+ const filteredScalars = ['String', 'Float', 'Int', 'Boolean'];
7
+ export class CustomTypeClassVisitor extends BaseJavaVisitor {
8
+ constructor(schema, rawConfig) {
9
+ super(schema, rawConfig, {
10
+ typePackage: rawConfig.typePackage || 'type',
11
+ });
12
+ }
13
+ extract(name) {
14
+ const lastIndex = name.lastIndexOf('.');
15
+ if (lastIndex === -1) {
16
+ return {
17
+ className: name,
18
+ importFrom: Imports[name] || null,
19
+ };
20
+ }
21
+ return {
22
+ className: name.substring(lastIndex + 1),
23
+ importFrom: name,
24
+ };
25
+ }
26
+ additionalContent() {
27
+ this._imports.add(Imports.ScalarType);
28
+ this._imports.add(Imports.Class);
29
+ this._imports.add(Imports.Override);
30
+ this._imports.add(Imports.Generated);
31
+ const allTypes = this._schema.getTypeMap();
32
+ const enumValues = Object.keys(allTypes)
33
+ .filter(t => isScalarType(allTypes[t]) && !filteredScalars.includes(t))
34
+ .map(t => allTypes[t])
35
+ .map(scalarType => {
36
+ const uppercaseName = scalarType.name.toUpperCase();
37
+ const javaType = this.extract(this.scalars[scalarType.name] || 'String');
38
+ if (javaType.importFrom) {
39
+ this._imports.add(javaType.importFrom);
40
+ }
41
+ return indentMultiline(`${uppercaseName} {
42
+ @Override
43
+ public String typeName() {
44
+ return "${scalarType.name}";
45
+ }
46
+
47
+ @Override
48
+ public Class javaType() {
49
+ return ${javaType.className}.class;
50
+ }
51
+ }`);
52
+ })
53
+ .join(',\n\n');
54
+ return new JavaDeclarationBlock()
55
+ .annotate([`Generated("Apollo GraphQL")`])
56
+ .access('public')
57
+ .asKind('enum')
58
+ .withName('CustomType')
59
+ .implements(['ScalarType'])
60
+ .withBlock(enumValues).string;
61
+ }
62
+ getPackage() {
63
+ return this.config.typePackage;
64
+ }
65
+ }
@@ -0,0 +1,32 @@
1
+ import { Imports } from './imports.js';
2
+ import { oldVisit } from '@graphql-codegen/plugin-helpers';
3
+ export function visitFieldArguments(selection, imports) {
4
+ if (!selection.arguments || selection.arguments.length === 0) {
5
+ return 'null';
6
+ }
7
+ imports.add(Imports.UnmodifiableMapBuilder);
8
+ imports.add(Imports.String);
9
+ imports.add(Imports.Object);
10
+ return oldVisit(selection, {
11
+ leave: {
12
+ Field: (node) => {
13
+ return (`new UnmodifiableMapBuilder<String, Object>(${node.arguments.length})` + node.arguments.join('') + '.build()');
14
+ },
15
+ Argument: (node) => {
16
+ return `.put("${node.name.value}", ${node.value})`;
17
+ },
18
+ ObjectValue: (node) => {
19
+ return `new UnmodifiableMapBuilder<String, Object>(${node.fields.length})` + node.fields.join('') + '.build()';
20
+ },
21
+ ObjectField: (node) => {
22
+ return `.put("${node.name.value}", ${node.value})`;
23
+ },
24
+ Variable: (node) => {
25
+ return `new UnmodifiableMapBuilder<String, Object>(2).put("kind", "Variable").put("variableName", "${node.name.value}").build()`;
26
+ },
27
+ StringValue: (node) => `"${node.value}"`,
28
+ IntValue: (node) => `"${node.value}"`,
29
+ FloatValue: (node) => `"${node.value}"`,
30
+ },
31
+ });
32
+ }
@@ -0,0 +1,7 @@
1
+ export var FileType;
2
+ (function (FileType) {
3
+ FileType[FileType["INPUT_TYPE"] = 0] = "INPUT_TYPE";
4
+ FileType[FileType["OPERATION"] = 1] = "OPERATION";
5
+ FileType[FileType["FRAGMENT"] = 2] = "FRAGMENT";
6
+ FileType[FileType["CUSTOM_TYPES"] = 3] = "CUSTOM_TYPES";
7
+ })(FileType || (FileType = {}));
package/esm/imports.js ADDED
@@ -0,0 +1,42 @@
1
+ export const Imports = {
2
+ // Primitives
3
+ String: 'java.lang.String',
4
+ Boolean: 'java.lang.Boolean',
5
+ Integer: 'java.lang.Integer',
6
+ Object: 'java.lang.Object',
7
+ Float: 'java.lang.Float',
8
+ Long: 'java.lang.Long',
9
+ // Java Base
10
+ Class: 'java.lang.Class',
11
+ Arrays: 'java.util.Arrays',
12
+ List: 'java.util.List',
13
+ IOException: 'java.io.IOException',
14
+ Collections: 'java.util.Collections',
15
+ LinkedHashMap: 'java.util.LinkedHashMap',
16
+ Map: 'java.util.Map',
17
+ // Annotations
18
+ Nonnull: 'javax.annotation.Nonnull',
19
+ Nullable: 'javax.annotation.Nullable',
20
+ Override: 'java.lang.Override',
21
+ Generated: 'javax.annotation.Generated',
22
+ // Apollo Android
23
+ ScalarType: 'com.apollographql.apollo.api.ScalarType',
24
+ GraphqlFragment: 'com.apollographql.apollo.api.GraphqlFragment',
25
+ Operation: 'com.apollographql.apollo.api.Operation',
26
+ OperationName: 'com.apollographql.apollo.api.OperationName',
27
+ Mutation: 'com.apollographql.apollo.api.Mutation',
28
+ Query: 'com.apollographql.apollo.api.Query',
29
+ Subscription: 'com.apollographql.apollo.api.Subscription',
30
+ ResponseField: 'com.apollographql.apollo.api.ResponseField',
31
+ ResponseFieldMapper: 'com.apollographql.apollo.api.ResponseFieldMapper',
32
+ ResponseFieldMarshaller: 'com.apollographql.apollo.api.ResponseFieldMarshaller',
33
+ ResponseReader: 'com.apollographql.apollo.api.ResponseReader',
34
+ ResponseWriter: 'com.apollographql.apollo.api.ResponseWriter',
35
+ FragmentResponseFieldMapper: 'com.apollographql.apollo.api.FragmentResponseFieldMapper',
36
+ UnmodifiableMapBuilder: 'com.apollographql.apollo.api.internal.UnmodifiableMapBuilder',
37
+ Utils: 'com.apollographql.apollo.api.internal.Utils',
38
+ InputType: 'com.apollographql.apollo.api.InputType',
39
+ Input: 'com.apollographql.apollo.api.Input',
40
+ InputFieldMarshaller: 'com.apollographql.apollo.api.InputFieldMarshaller',
41
+ InputFieldWriter: 'com.apollographql.apollo.api.InputFieldWriter',
42
+ };
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './plugin.js';
2
+ export * from './preset.js';
@@ -0,0 +1,183 @@
1
+ import { getBaseTypeNode, indent, indentMultiline } from '@graphql-codegen/visitor-plugin-common';
2
+ import { JavaDeclarationBlock } from '@graphql-codegen/java-common';
3
+ import { isScalarType, isInputObjectType, Kind, isEnumType, } from 'graphql';
4
+ import { Imports } from './imports.js';
5
+ import { BaseJavaVisitor, SCALAR_TO_WRITER_METHOD } from './base-java-visitor.js';
6
+ export class InputTypeVisitor extends BaseJavaVisitor {
7
+ constructor(_schema, rawConfig) {
8
+ super(_schema, rawConfig, {
9
+ typePackage: rawConfig.typePackage || 'type',
10
+ });
11
+ }
12
+ getPackage() {
13
+ return this.config.typePackage;
14
+ }
15
+ addInputMembers(cls, fields) {
16
+ fields.forEach(field => {
17
+ const type = this.transformType(field.type);
18
+ const actualType = type.isNonNull ? type.typeToUse : `Input<${type.typeToUse}>`;
19
+ const annotations = type.isNonNull ? [type.annotation] : [];
20
+ this._imports.add(Imports[type.annotation]);
21
+ cls.addClassMember(field.name.value, actualType, null, annotations, 'private', { final: true });
22
+ cls.addClassMethod(field.name.value, actualType, `return this.${field.name.value};`, [], [type.annotation], 'public');
23
+ });
24
+ }
25
+ addInputCtor(cls, className, fields) {
26
+ const impl = fields.map(field => `this.${field.name.value} = ${field.name.value};`).join('\n');
27
+ cls.addClassMethod(className, null, impl, fields.map(f => {
28
+ const type = this.transformType(f.type);
29
+ const actualType = type.isNonNull ? type.typeToUse : `Input<${type.typeToUse}>`;
30
+ this._imports.add(Imports[type.annotation]);
31
+ return {
32
+ name: f.name.value,
33
+ type: actualType,
34
+ annotations: type.isNonNull ? [type.annotation] : [],
35
+ };
36
+ }), [], 'public');
37
+ }
38
+ getFieldWriterCall(field, listItemCall = false) {
39
+ const baseType = getBaseTypeNode(field.type);
40
+ const schemaType = this._schema.getType(baseType.name.value);
41
+ const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
42
+ let writerMethod = null;
43
+ if (isScalarType(schemaType)) {
44
+ writerMethod = SCALAR_TO_WRITER_METHOD[schemaType.name] || 'writeCustom';
45
+ }
46
+ else if (isInputObjectType(schemaType)) {
47
+ return listItemCall
48
+ ? `writeObject($item.marshaller())`
49
+ : `writeObject("${field.name.value}", ${field.name.value}.value != null ? ${field.name.value}.value.marshaller() : null)`;
50
+ }
51
+ else if (isEnumType(schemaType)) {
52
+ writerMethod = 'writeString';
53
+ }
54
+ return listItemCall
55
+ ? `${writerMethod}($item)`
56
+ : `${writerMethod}("${field.name.value}", ${field.name.value}${isNonNull ? '' : '.value'})`;
57
+ }
58
+ getFieldWithTypePrefix(field, wrapWith = null, applyNullable = false) {
59
+ this._imports.add(Imports.Input);
60
+ const typeToUse = this.getJavaClass(this._schema.getType(getBaseTypeNode(field.type).name.value));
61
+ const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
62
+ const name = field.kind === Kind.INPUT_VALUE_DEFINITION ? field.name.value : field.variable.name.value;
63
+ if (isNonNull) {
64
+ this._imports.add(Imports.Nonnull);
65
+ return `@Nonnull ${typeToUse} ${name}`;
66
+ }
67
+ if (wrapWith) {
68
+ return typeof wrapWith === 'function' ? `${wrapWith(typeToUse)} ${name}` : `${wrapWith}<${typeToUse}> ${name}`;
69
+ }
70
+ if (applyNullable) {
71
+ this._imports.add(Imports.Nullable);
72
+ }
73
+ return `${applyNullable ? '@Nullable ' : ''}${typeToUse} ${name}`;
74
+ }
75
+ buildFieldsMarshaller(field) {
76
+ const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
77
+ const isArray = field.type.kind === Kind.LIST_TYPE ||
78
+ (field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
79
+ const call = this.getFieldWriterCall(field, isArray);
80
+ const baseTypeNode = getBaseTypeNode(field.type);
81
+ const listItemType = this.getJavaClass(this._schema.getType(baseTypeNode.name.value));
82
+ let result = '';
83
+ // TODO: Refactor
84
+ if (isArray) {
85
+ result = `writer.writeList("${field.name.value}", ${field.name.value}.value != null ? new InputFieldWriter.ListWriter() {
86
+ @Override
87
+ public void write(InputFieldWriter.ListItemWriter listItemWriter) throws IOException {
88
+ for (${listItemType} $item : ${field.name.value}.value) {
89
+ listItemWriter.${call};
90
+ }
91
+ }
92
+ } : null);`;
93
+ }
94
+ else {
95
+ result = indent(`writer.${call};`);
96
+ }
97
+ if (isNonNull) {
98
+ return result;
99
+ }
100
+ return indentMultiline(`if(${field.name.value}.defined) {
101
+ ${indentMultiline(result)}
102
+ }`);
103
+ }
104
+ buildMarshallerOverride(fields) {
105
+ this._imports.add(Imports.Override);
106
+ this._imports.add(Imports.IOException);
107
+ this._imports.add(Imports.InputFieldWriter);
108
+ this._imports.add(Imports.InputFieldMarshaller);
109
+ const allMarshallers = fields.map(field => indentMultiline(this.buildFieldsMarshaller(field), 2));
110
+ return indentMultiline(`@Override
111
+ public InputFieldMarshaller marshaller() {
112
+ return new InputFieldMarshaller() {
113
+ @Override
114
+ public void marshal(InputFieldWriter writer) throws IOException {
115
+ ${allMarshallers.join('\n')}
116
+ }
117
+ };
118
+ }`);
119
+ }
120
+ buildBuilderNestedClass(className, fields) {
121
+ const builderClassName = 'Builder';
122
+ const privateFields = fields
123
+ .map(field => {
124
+ const isArray = field.type.kind === Kind.LIST_TYPE ||
125
+ (field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
126
+ const fieldType = this.getFieldWithTypePrefix(field, v => (!isArray ? `Input<${v}>` : `Input<List<${v}>>`));
127
+ const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
128
+ return `private ${fieldType}${isNonNull ? '' : ' = Input.absent()'};`;
129
+ })
130
+ .map(s => indent(s));
131
+ const setters = fields
132
+ .map(field => {
133
+ const isArray = field.type.kind === Kind.LIST_TYPE ||
134
+ (field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
135
+ const fieldType = this.getFieldWithTypePrefix(field, isArray ? 'List' : null);
136
+ const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
137
+ return `\npublic ${builderClassName} ${field.name.value}(${isNonNull ? '' : '@Nullable '}${fieldType}) {
138
+ this.${field.name.value} = ${isNonNull ? field.name.value : `Input.fromNullable(${field.name.value})`};
139
+ return this;
140
+ }`;
141
+ })
142
+ .map(s => indentMultiline(s));
143
+ const nonNullFields = fields
144
+ .filter(f => f.type.kind === Kind.NON_NULL_TYPE)
145
+ .map(nnField => {
146
+ this._imports.add(Imports.Utils);
147
+ return indent(`Utils.checkNotNull(${nnField.name.value}, "${nnField.name.value} == null");`, 1);
148
+ });
149
+ const ctor = '\n' + indent(`${builderClassName}() {}`);
150
+ const buildFn = indentMultiline(`public ${className} build() {
151
+ ${nonNullFields.join('\n')}
152
+ return new ${className}(${fields.map(f => f.name.value).join(', ')});
153
+ }`);
154
+ const body = [...privateFields, ctor, ...setters, '', buildFn].join('\n');
155
+ return indentMultiline(new JavaDeclarationBlock()
156
+ .withName(builderClassName)
157
+ .access('public')
158
+ .final()
159
+ .static()
160
+ .withBlock(body)
161
+ .asKind('class').string);
162
+ }
163
+ InputObjectTypeDefinition(node) {
164
+ const className = node.name.value;
165
+ this._imports.add(Imports.InputType);
166
+ this._imports.add(Imports.Generated);
167
+ const cls = new JavaDeclarationBlock()
168
+ .annotate([`Generated("Apollo GraphQL")`])
169
+ .access('public')
170
+ .final()
171
+ .asKind('class')
172
+ .withName(className)
173
+ .implements(['InputType']);
174
+ this.addInputMembers(cls, node.fields);
175
+ this.addInputCtor(cls, className, node.fields);
176
+ cls.addClassMethod('builder', 'Builder', 'return new Builder();', [], [], 'public', { static: true });
177
+ const marshallerOverride = this.buildMarshallerOverride(node.fields);
178
+ const builderClass = this.buildBuilderNestedClass(className, node.fields);
179
+ const classBlock = [marshallerOverride, '', builderClass].join('\n');
180
+ cls.withBlock(classBlock);
181
+ return cls.string;
182
+ }
183
+ }