class GraphQLJavaGen

Constants

BUILTIN_SCALARS
DEFAULT_SCALAR
RESERVED_WORDS

From: docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html

TEMPLATE_ERB
VERSION

Attributes

imports[R]
include_deprecated[R]
package_name[R]
scalars[R]
schema[R]
schema_name[R]
script_name[R]
version[R]

Public Class Methods

new(schema, package_name:, nest_under:, script_name: 'graphql_java_gen gem', custom_scalars: [], custom_annotations: [], include_deprecated: false, version: '' ) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 12
def initialize(schema,
  package_name:, nest_under:, script_name: 'graphql_java_gen gem',
  custom_scalars: [], custom_annotations: [], include_deprecated: false, version: ''
)
  @schema = schema
  @schema_name = nest_under
  @script_name = script_name
  @package_name = package_name
  @scalars = (BUILTIN_SCALARS + custom_scalars).reduce({}) { |hash, scalar| hash[scalar.type_name] = scalar; hash }
  @scalars.default_proc = ->(hash, key) { DEFAULT_SCALAR }
  @annotations = custom_annotations
  @imports = (@scalars.values.map(&:imports) + @annotations.map(&:imports)).flatten.sort.uniq
  @include_deprecated = include_deprecated
  @version = version
end

Private Class Methods

erb_for(template_filename) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 49
def erb_for(template_filename)
  erb = ERB.new(File.read(template_filename), nil, '-')
  erb.filename = template_filename
  erb
end

Public Instance Methods

generate() click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 40
def generate
  reformat(TEMPLATE_ERB.result(binding))
end
save(path) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 28
def save(path)
  File.write(path, generate)
end
save_granular(path) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 32
def save_granular(path)
  write_schema(path)
  write_static_methods(path)
  write_response(path, :query, schema.query_root_name)
  write_response(path, :mutation, schema.mutation_root_name)
  write_entities(path)
end

Private Instance Methods

abstract_types() click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 328
def abstract_types
  @abstract_types ||= schema.types.each_with_object({}) do |type, result|
    case type.kind
    when 'OBJECT'
      result[type.name] ||= Set.new
    when 'INTERFACE', 'UNION'
      type.possible_types.each do |possible_type|
        (result[possible_type.name] ||= Set.new).add(type.name)
      end
    end
  end
end
erb_for_entity(template) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 59
def erb_for_entity(template)
  template_filename = File.expand_path("../graphql_java_gen/templates/#{template}.erb", __FILE__)
  erb = ERB.new(File.read(template_filename), nil, '-')
  erb.filename = template_filename
  erb
end
escape_reserved_word(word) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 149
def escape_reserved_word(word)
  return word unless RESERVED_WORDS.include?(word)
  "#{word}Value"
end
generate_build_input_code(expr, type, depth: 1) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 187
  def generate_build_input_code(expr, type, depth: 1)
    type = type.unwrap_non_null
    case type.kind
    when 'SCALAR'
      if ['Int', 'Float', 'Boolean'].include?(type.name)
        "_queryBuilder.append(#{expr});"
      else
        "Query.appendQuotedString(_queryBuilder, #{expr}.toString());"
      end
    when 'ENUM'
      "_queryBuilder.append(#{expr}.toString());"
    when 'LIST'
      item_type = type.of_type
      <<-JAVA
        _queryBuilder.append('[');
        {
          String listSeperator#{depth} = "";
          for (#{java_input_type(item_type)} item#{depth} : #{expr}) {
            _queryBuilder.append(listSeperator#{depth});
            listSeperator#{depth} = ",";
            #{generate_build_input_code("item#{depth}", item_type, depth: depth + 1)}
          }
        }
        _queryBuilder.append(']');
      JAVA
    when 'INPUT_OBJECT'
      "#{expr}.appendTo(_queryBuilder);"
    else
      raise NotImplementedError, "Unexpected #{type.kind} argument type"
    end
  end
generate_build_output_code(expr, type, depth: 1, non_null: false) { |statements, optional_name| ... } click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 219
  def generate_build_output_code(expr, type, depth: 1, non_null: false, &block)
    if type.non_null?
      return generate_build_output_code(expr, type.of_type, depth: depth, non_null: true, &block)
    end

    statements = ""
    unless non_null
      optional_name = "optional#{depth}"
      generate_build_output_code(expr, type, depth: depth, non_null: true) do |item_statements, item_expr|
        statements = <<-JAVA
          #{java_output_type(type)} #{optional_name} = null;
          if (!#{expr}.isJsonNull()) {
            #{item_statements}
            #{optional_name} = #{item_expr};
          }
        JAVA
      end
      return yield statements, optional_name
    end

    expr = case type.kind
    when 'SCALAR'
      scalars[type.name].deserialize(expr)
    when 'LIST'
      list_name = "list#{depth}"
      element_name = "element#{depth}"
      generate_build_output_code(element_name, type.of_type, depth: depth + 1) do |item_statements, item_expr|
        statements = <<-JAVA
          #{java_output_type(type)} #{list_name} = new ArrayList<>();
          for (JsonElement #{element_name} : jsonAsArray(#{expr}, key)) {
            #{item_statements}
            #{list_name}.add(#{item_expr});
          }
        JAVA
      end
      list_name
    when 'OBJECT'
      "new #{type.name}(jsonAsObject(#{expr}, key))"
    when 'INTERFACE', 'UNION'
      "Unknown#{type.name}.create(jsonAsObject(#{expr}, key))"
    when 'ENUM'
       "#{type.name}.fromGraphQl(jsonAsString(#{expr}, key))"
    else
      raise NotImplementedError, "Unexpected #{type.kind} argument type"
    end
    yield statements, expr
  end
generate_entity(template, type) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 66
def generate_entity(template, type)
  erb_template = erb_for_entity(template)
  reformat(erb_template.result(binding))
end
java_annotations(field, in_argument: false) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 311
def java_annotations(field, in_argument: false)
  annotations = @annotations.map do |annotation|
    "@#{annotation.name}" if annotation.annotate?(field)
  end.compact
  return "" unless annotations.any?

  if in_argument
    annotations.join(" ") + " "
  else
    annotations.join("\n")
  end
end
java_arg_defs(field, skip_optional: false) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 267
def java_arg_defs(field, skip_optional: false)
  defs = []
  field.required_args.each do |arg|
    defs << "#{java_input_type(arg.type)} #{escape_reserved_word(arg.camelize_name)}"
  end
  unless field.optional_args.empty? || skip_optional
    defs << "#{field.classify_name}ArgumentsDefinition argsDef"
  end
  if field.subfields?
    defs << "#{field.type.unwrap.name}QueryDefinition queryDef"
  end
  defs.join(', ')
end
java_arg_expresions_with_empty_optional_args(field) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 295
def java_arg_expresions_with_empty_optional_args(field)
  expressions = field.required_args.map { |arg| escape_reserved_word(arg.camelize_name) }
  expressions << "args -> {}"
  if field.subfields?
    expressions << "queryDef"
  end
  expressions.join(', ')
end
java_doc(element) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 341
def java_doc(element)
  doc = ''
  unless element.description.nil?
    description = wrap_text(element.description, 100)
    description = description.chomp("\n").gsub("\n", "\n* ")
    doc << '* '
    doc << description
  end

  if element.respond_to?(:deprecated?) && element.deprecated?
    unless doc.empty?
      doc << "\n*"
      doc << "\n*"
    else
      doc << '*'        
    end
    doc << ' @deprecated '
    doc << element.deprecation_reason
  end

  doc.empty? ? doc : "/**\n" + doc + "\n*/"
end
java_implements(type) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 304
def java_implements(type)
  return "implements #{type.name} " unless type.object?
  interfaces = abstract_types.fetch(type.name)
  return "" if interfaces.empty?
  "implements #{interfaces.to_a.join(', ')} "
end
java_input_type(type, non_null: false) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 158
def java_input_type(type, non_null: false)
  case type.kind
  when "NON_NULL"
    java_input_type(type.of_type, non_null: true)
  when "SCALAR"
    non_null ? scalars[type.name].non_nullable_type : scalars[type.name].nullable_type
  when 'LIST'
    "List<#{java_input_type(type.of_type.unwrap_non_null)}>"
  when 'INPUT_OBJECT', 'ENUM'
    type.name
  else
    raise NotImplementedError, "Unhandled #{type.kind} input type"
  end
end
java_output_type(type) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 173
def java_output_type(type)
  type = type.unwrap_non_null
  case type.kind
  when "SCALAR"
    scalars[type.name].nullable_type
  when 'LIST'
    "List<#{java_output_type(type.of_type)}>"
  when 'ENUM', 'OBJECT', 'INTERFACE', 'UNION'
    type.name
  else
    raise NotImplementedError, "Unhandled #{type.kind} response type"
  end
end
java_required_arg_defs(field) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 281
def java_required_arg_defs(field)
  defs = []
  field.required_args.each do |arg|
    defs << "#{java_input_type(arg.type)} #{escape_reserved_word(arg.camelize_name)}"
  end
  unless field.optional_args.empty?
    defs << "#{field.classify_name}ArgumentsDefinition argsDef"
  end
  if field.subfields?
    defs << "#{field.type.unwrap.classify_name}QueryDefinition queryDef"
  end
  defs.join(', ')
end
reformat(code) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 154
def reformat(code)
  Reformatter.new(indent: " " * 4).reformat(code)
end
type_names_set() click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 324
def type_names_set
  @type_names_set ||= schema.types.map(&:name).to_set
end
wrap_text(text, col_width=80) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 364
def wrap_text(text, col_width=80)
  text.gsub!( /(\S{#{col_width}})(?=\S)/, '\1 ' )
  text.gsub!( /(.{1,#{col_width}})(?:\s+|$)/, "\\1\n" )
  text
end
write_entities(path) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 85
def write_entities(path)
  schema.types.reject{ |type| type.name.start_with?('__') || type.scalar? }.each do |type|
    case type.kind when 'OBJECT', 'INTERFACE', 'UNION'
                     File.write(path + "/#{type.name}QueryDefinition.java", generate_entity("QueryDefinition.java", type))
                     File.write(path + "/#{type.name}Query.java", generate_entity("Query.java", type))
                     File.write(path + "/#{type.name}.java", generate_entity("Interface.java", type))

                     class_name = type.object? ? type.name : "Unknown#{type.name}"
                     File.write(path + "/#{class_name}.java", generate_entity("Object.java", type))
      when 'INPUT_OBJECT'
        File.write(path + "/#{type.name}.java", generate_entity("Input.java", type))
      when 'ENUM'
        File.write(path + "/#{type.name}.java", generate_entity("Enum.java", type))
      else
        raise NotImplementedError, "unhandled #{type.kind} type #{type.name}"
    end
  end
end
write_response(path, query, root_name) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 79
def write_response(path, query, root_name)
  response_type = query.to_s.capitalize
  response = reformat(erb_for_entity("Responses.java").result(binding))
  File.write(path + "/#{response_type}Response.java", response)
end
write_schema(path) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 71
def write_schema(path)
  File.write(path + "/Schema.java", reformat(erb_for_entity("Schema.java").result(binding)))
end
write_static_methods(path) click to toggle source
# File codegen/lib/graphql_java_gen.rb, line 75
def write_static_methods(path)
  File.write(path + "/Operations.java", reformat(erb_for_entity("Operations.java").result(binding)))
end