class JavaLanguageModel(language_model.LanguageModel):
    """A LanguageModel tuned for Java."""

    language = 'java'

    _JSON_STRING_IMPORT = 'com.google.api.client.json.JsonString'
    _JSON_STRING_TEMPLATE_VALUE = 'requiresJsonString'
    member_policy = language_model.NamingPolicy(
        language_model.LOWER_CAMEL_CASE)
    getter_policy = language_model.NamingPolicy(
        language_model.UPPER_CAMEL_CASE, 'get{name}')
    setter_policy = language_model.NamingPolicy(
        language_model.UPPER_CAMEL_CASE, 'set{name}')
    has_policy = language_model.NamingPolicy(language_model.UPPER_CAMEL_CASE,
                                             'has{name}')
    array_of_policy = language_model.NamingPolicy(
        format_string='java.util.List<{name}>')
    map_of_policy = language_model.NamingPolicy(
        format_string='java.util.Map<String, {name}>')
    constant_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_UNCAMEL_CASE, separator='_')
    enum_policy = language_model.NamingPolicy(language_model.UPPER_CAMEL_CASE,
                                              format_string='{name}Values')

    # Dictionary of json type and format to its corresponding data type and
    # import definition. The first import in the imports list is the primary
    # import.
    _TYPE_BOOLEAN = _SimpleType('java.lang.Boolean', primative_type='boolean')
    _TYPE_DOUBLE = _SimpleType('java.lang.Double', primative_type='double')
    _TYPE_FLOAT = _SimpleType('java.lang.Float', primative_type='float')
    _TYPE_INTEGER = _SimpleType('java.lang.Integer', primative_type='int')
    _TYPE_LONG = _SimpleType('java.lang.Long', primative_type='long')
    _TYPE_SHORT = _SimpleType('java.lang.Short', primative_type='short')
    _TYPE_DATETIME = ('com.google.api.client.util.DateTime',
                      ImportDefinition(['com.google.api.client.util.DateTime'
                                        ]), None)
    _TYPE_STRING = _SimpleType('java.lang.String')

    _TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = {
        ('any', None):
        _SimpleType('java.lang.Object'),
        ('boolean', None):
        _TYPE_BOOLEAN,
        ('integer', None):
        _TYPE_INTEGER,
        ('integer', 'int16'):
        _TYPE_SHORT,
        ('integer', 'int32'):
        _TYPE_INTEGER,
        # We prefer Long here over UnsignedInteger because Long has built-in
        # support for autoboxing in Java.
        ('integer', 'uint32'):
        _TYPE_LONG,
        # TODO(user): Switch to java.lang.Number in a separate CL.
        # ('number', None): _SimpleType('java.lang.Number'),
        ('number', None): ('Number', ImportDefinition(), None),
        ('number', 'double'):
        _TYPE_DOUBLE,
        ('number', 'float'):
        _TYPE_FLOAT,
        ('object', None):
        _SimpleType('java.lang.Object'),
        ('string', None):
        _TYPE_STRING,
        ('string', 'byte'):
        _TYPE_STRING,
        ('string', 'date'):
        _TYPE_DATETIME,
        ('string', 'date-time'):
        _TYPE_DATETIME,
        ('string', 'int64'):
        ('java.lang.Long',
         ImportDefinition(['java.lang.Long', _JSON_STRING_IMPORT],
                          [_JSON_STRING_TEMPLATE_VALUE]), 'long'),
        ('string', 'uint64'):
        ('java.math.BigInteger',
         ImportDefinition(['java.math.BigInteger', _JSON_STRING_IMPORT],
                          [_JSON_STRING_TEMPLATE_VALUE]), None),
    }

    _JAVA_KEYWORDS = [
        'abstract', 'assert', 'boolean', 'break', 'byte', 'case', 'catch',
        'char', 'class', 'const', 'continue', 'default', 'do', 'double',
        'else', 'enum', 'extends', 'final', 'finally', 'float', 'for', 'goto',
        'if', 'implements', 'import', 'instanceof', 'int', 'interface', 'long',
        'native', 'new', 'package', 'private', 'protected', 'public', 'return',
        'short', 'static', 'strictfp', 'super', 'switch', 'synchronized',
        'this', 'throw', 'throws', 'transient', 'try', 'void', 'volatile',
        'while'
    ]

    # TODO(user): Remove this. We should instead be using fully qualified names
    # for models to avoid collisions. This will be fixed in Bug 6448720.
    _SPECIAL_CLASS_NAMES = [
        # Required because GenericData extends AbstractMap<String, Object>
        'entry'
    ]

    # We can not create classes which match a Java keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _JAVA_KEYWORDS + _SPECIAL_CLASS_NAMES + [
        'float', 'integer', 'object', 'string', 'true', 'false', 'null'
    ]

    allowed_characters = '$'
    reserved_words = RESERVED_CLASS_NAMES

    def __init__(self, options=None):
        super(JavaLanguageModel, self).__init__(class_name_delimiter='.')
        self._type_map = JavaLanguageModel._TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS

        self._SUPPORTED_TYPES['boolean'] = self._Boolean
        self._SUPPORTED_TYPES['integer'] = self._Int
        self._options = options

    def _Boolean(self, data_value):
        """Convert provided boolean to language specific literal."""
        return unicode(bool(data_value.value)).lower()

    def _Int(self, data_value):
        """Convert provided int to language specific literal."""
        # Available types can be found in class variables
        code_types = {
            'java.lang.Short': '%s',
            'java.lang.Integer': '%s',
            'java.lang.Long': '%sL',
        }
        try:
            return code_types[data_value.code_type] % long(data_value.value)
        except KeyError:
            raise ValueError((
                'Provided DataValue (%s) does not present an appropriate Java '
                'annotated code type (%s).') %
                             (data_value.value, data_value.code_type))

    @property
    def type_map(self):
        return self._type_map

    def _GetTypeInfo(self, def_dict):
        """Returns a tuple of type information for a json schema data dict.

    For the dictionary containing {type, [format]}, return the tuple of the form
      (Java class name, ImportDefinition, Java primitive data type)
    describing the appropriate Java data type.

    Args:
      def_dict: (dict) JSON schema data definition.
    Returns:
      tuple of (class name, ImportDefinition, primitive data type).
    """
        json_type = def_dict.get('type', 'string')
        json_format = def_dict.get('format')
        result = self.type_map.get((json_type, json_format))
        if result:
            return result

        # TODO(user): Uncomment this and update golden files.
        # result = self.type_map.get((json_type, None))
        # if result:
        #   return result
        #
        # raise ValueError('Unknown type: %s format: %s' % (json_type, json_format))

        return (utilities.CamelCase(json_type), None, None)

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json schema type to a suitable Java type name.

    Overrides the default.

    Args:
      def_dict: (dict) A dictionary describing Json schema for this Property.
    Returns:
      A name suitable for use as a class in the generator's target language.
    """
        return self._GetTypeInfo(def_dict)[0]

    def GetPrimitiveTypeFromDictionary(self, def_dict):
        """Convert a json schema type to a suitable Java primitive name or None.

    Overrides the default.

    Args:
      def_dict: (dict) A dictionary describing Json schema for this Property.
    Returns:
      A name suitable for use as a primitive in the generator's target language.
    """
        return self._GetTypeInfo(def_dict)[2]

    def ToMemberName(self, s, the_api):
        """CamelCase a wire format name into a suitable Java variable name."""
        camel_s = utilities.CamelCase(s)
        if s.lower() in JavaLanguageModel.RESERVED_CLASS_NAMES:
            # Prepend the service name
            return '%s%s' % (the_api.values['name'], camel_s)
        return camel_s[0].lower() + camel_s[1:]

    def ToSafeClassName(self, s, the_api, parent=None):
        """Convert a name to a suitable class name in Java.

    Subclasses should override as appropriate.

    Args:
      s: (str) A canonical name for data element. (Usually the API wire format)
      the_api: (Api) The API this element is part of. For use as a hint when the
        name cannot be used directly.
      parent: (schema) The parent we use to get a safe class name.
    Returns:
      A name suitable for use as an element in Java.
    """
        safe_class_name = utilities.CamelCase(s)
        if parent:
            for ancestor in parent.full_path:
                if ancestor.safeClassName == safe_class_name:
                    safe_class_name = '%s%s' % (parent.class_name,
                                                safe_class_name)
        if safe_class_name.lower() in JavaLanguageModel.RESERVED_CLASS_NAMES:
            api_name = utilities.CamelCase(the_api.values['name'])
            if utilities.CamelCase(the_api.values['canonicalName']):
                # Use canonical name if specified.
                api_name = utilities.CamelCase(
                    the_api.values['canonicalName']).replace(' ', '')
            # Prepend the API name
            safe_class_name = '%s%s' % (api_name, utilities.CamelCase(s))
        return safe_class_name

    def ToPropertyGetterMethodWithDelim(self, prop_name):
        """Convert a property name to the name of the getter method that returns it.

    Args:
      prop_name: (str) The name of a property.
    Returns:
      A Java specific name of the getter method that returns the specified
      property. Eg: returns .getXyz for a property called xyz.
    """
        return '%sget%s()' % (self._class_name_delimiter,
                              utilities.CamelCase(prop_name))

    def CodeTypeForVoid(self):
        """Return the Java type name for a void.

    Overrides the default.

    Returns:
      (str) 'EmptyResponse'
    """
        return 'Void'

    def DefaultContainerPathForOwner(self, module):
        """Overrides the default."""
        if module.owner_domain == 'google.com':
            if ((self._options and self._options.get('google_api'))
                    or not module.package_path):
                return 'com/google/api/services'
        return '/'.join(utilities.ReversedDomainComponents(
            module.owner_domain))
def _SimpleType(class_name, primative_type=None):
    """Type definition for classes with no primitives or special imports."""
    return (class_name, ImportDefinition([class_name]), primative_type)
    def _BuildTypeMap(self, options=None):
        """Builds the map of discovery document types to C++ types.

    Args:
      options: (dict) Code generator options.

    Returns:
      map of (discovery type, format) keys to (C++ type, import value)
      values where the import value is header file name to include.
    """
        self.global_namespace_ = ''
        self.client_namespace_ = 'client'
        builtin_type_h = None
        integral_type_h = '"googleapis/base/integral_types.h"'
        json_type_h = '"googleapis/client/data/jsoncpp_data.h"'
        # TODO(user): Implement open-source date.h
        date_time_h = '"googleapis/client/util/date_time.h"'
        date_h = date_time_h
        self.date_namespace_ = self.client_namespace_

        # Dictionary of json type and format to its corresponding data type and
        # import definition. The first import in the imports list is the primary
        # import.
        return {
            ('boolean', None): ('bool', ImportDefinition([builtin_type_h])),
            ('any', None): (self.client_namespace_ + '::JsonCppData',
                            ImportDefinition([json_type_h])),
            ('integer', None): ('int32', ImportDefinition([integral_type_h])),
            ('integer', 'int16'):
            ('int16', ImportDefinition([integral_type_h])),
            ('integer', 'uint16'): ('uint16',
                                    ImportDefinition([integral_type_h])),
            ('integer', 'int32'):
            ('int32', ImportDefinition([integral_type_h])),
            ('integer', 'uint32'): ('uint32',
                                    ImportDefinition([integral_type_h])),
            ('number', None): ('double', ImportDefinition([builtin_type_h])),
            ('number', 'double'):
            ('double', ImportDefinition([builtin_type_h])),
            ('number', 'float'): ('float', ImportDefinition([builtin_type_h])),
            ('object', None): (self.client_namespace_ + '::JsonCppData',
                               ImportDefinition([json_type_h])),
            ('string', None): ('string', ImportDefinition(['<string>'])),
            ('string', 'byte'): ('string', ImportDefinition(['<string>'])),
            ('string', 'date'): (self.date_namespace_ + '::Date',
                                 ImportDefinition([date_h])),
            ('string', 'date-time'): (self.client_namespace_ + '::DateTime',
                                      ImportDefinition([date_time_h])),
            ('string', 'google-datetime'): ('string',
                                            ImportDefinition(['<string>'])),
            ('string', 'google-duration'): ('string',
                                            ImportDefinition(['<string>'])),
            ('string', 'google-fieldmask'): ('string',
                                             ImportDefinition(['<string>'])),
            ('string', 'int64'):
            ('int64', ImportDefinition([integral_type_h])),
            ('string', 'uint64'): ('uint64',
                                   ImportDefinition([integral_type_h])),
        }
Example #4
0
class JavaLanguageModel(LanguageModel):
    """A LanguageModel tuned for Java."""

    _JSON_STRING_IMPORT = 'com.google.api.client.json.JsonString'
    _JSON_STRING_TEMPLATE_VALUE = 'requiresJsonString'

    # Dictionary of json type and format to its corresponding data type and
    # import definition. The first import in the imports list is the primary
    # import.
    TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = {
        ('boolean', None):
        ('Boolean', ImportDefinition(['java.lang.Boolean'])),
        ('any', None): ('Object', ImportDefinition(['java.lang.Object'])),
        ('integer', 'int16'): ('Short', ImportDefinition(['java.lang.Short'])),
        ('integer', 'int32'): ('Integer',
                               ImportDefinition(['java.lang.Integer'])),
        # Java does not support Unsigned Integers
        ('integer', 'uint32'): ('Long', ImportDefinition(['java.lang.Long'])),
        ('number', 'double'): ('Double', ImportDefinition(['java.lang.Double'
                                                           ])),
        ('number', 'float'): ('Float', ImportDefinition(['java.lang.Float'])),
        ('object', None): ('Object', ImportDefinition(['java.lang.Object'])),
        ('string', None): ('String', ImportDefinition(['java.lang.String'])),
        ('string', 'byte'): ('String', ImportDefinition(['java.lang.String'])),
        ('string', 'date-time'):
        ('DateTime', ImportDefinition(['com.google.api.client.util.DateTime'
                                       ])),
        ('string', 'int64'):
        ('Long',
         ImportDefinition(['java.lang.Long', _JSON_STRING_IMPORT],
                          [_JSON_STRING_TEMPLATE_VALUE])),
        # Java does not support Unsigned Integers
        ('string', 'uint64'):
        ('BigInteger',
         ImportDefinition(['java.math.BigInteger', _JSON_STRING_IMPORT],
                          [_JSON_STRING_TEMPLATE_VALUE])),
    }

    _JAVA_KEYWORDS = [
        'abstract', 'assert', 'boolean', 'break', 'byte', 'case', 'catch',
        'char', 'class', 'const', 'continue', 'default', 'do', 'double',
        'else', 'enum', 'extends', 'final', 'finally', 'float', 'for', 'goto',
        'if', 'implements', 'import', 'instanceof', 'int', 'interface', 'long',
        'native', 'new', 'package', 'private', 'protected', 'public', 'return',
        'short', 'static', 'strictfp', 'super', 'switch', 'synchronized',
        'this', 'throw', 'throws', 'transient', 'try', 'void', 'volatile',
        'while'
    ]

    # We can not create classes which match a Java keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _JAVA_KEYWORDS + [
        'float',
        'integer',
        'object',
        'string',
        'true',
        'false',
    ]

    def __init__(self):
        super(JavaLanguageModel, self).__init__(class_name_delimiter='.')
        self._type_map = JavaLanguageModel.TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS

    @property
    def type_map(self):
        return self._type_map

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json schema type to a suitable Java type name.

    Overrides the default.

    Args:
      def_dict: (dict) A dictionary describing Json schema for this Property.
    Returns:
      A name suitable for use as a class in the generator's target language.
    """
        json_type = def_dict.get('type', 'string')
        json_format = def_dict.get('format')

        datatype_and_imports = self._type_map.get((json_type, json_format))
        if datatype_and_imports:
            # If there is an entry in the type format to datatype and imports
            # dictionary set it as the native format.
            native_format = datatype_and_imports[0]
        else:
            # Could not find it in the dictionary, set it to the json type.
            native_format = utilities.CamelCase(json_type)
        return native_format

    def CodeTypeForArrayOf(self, type_name):
        """Take a type name and return the syntax for an array of them.

    Overrides the default.

    Args:
      type_name: (str) A type name.
    Returns:
      A language specific string meaning "an array of type_name".
    """
        return 'java.util.List<%s>' % type_name

    def CodeTypeForMapOf(self, type_name):
        """Take a type name and return the syntax for a map of String to them.

    Overrides the default.

    Args:
      type_name: (str) A type name.
    Returns:
      A language specific string meaning "an array of type_name".
    """
        return 'java.util.Map<String, %s>' % type_name

    def ToMemberName(self, s, the_api):
        """CamelCase a wire format name into a suitable Java variable name."""
        camel_s = utilities.CamelCase(s)
        if s.lower() in JavaLanguageModel.RESERVED_CLASS_NAMES:
            # Prepend the service name
            return '%s%s' % (the_api.values['name'], camel_s)
        return camel_s[0].lower() + camel_s[1:]
Example #5
0
class GwtLanguageModel(java_generator.JavaLanguageModel):
    """A LanguageModel for GWT."""

    # Dictionary of json type and format to its corresponding import definition.
    # The first import in the imports list is the primary import.
    TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = {
        ('boolean', None):
        ('Boolean', ImportDefinition(['java.lang.Boolean'])),
        # Use String instead of Object for GWT
        ('any', None): ('String', ImportDefinition(['java.lang.String'])),
        ('integer', 'int16'): ('Short', ImportDefinition(['java.lang.Short'])),
        ('integer', 'int32'): ('Integer',
                               ImportDefinition(['java.lang.Integer'])),
        # Java does not support Unsigned Integers
        ('integer', 'uint32'): ('Long', ImportDefinition(['java.lang.Long'])),
        ('number', 'double'):
        ('Double', ImportDefinition(['java.lang.Double'])),
        ('number', 'float'): ('Float', ImportDefinition(['java.lang.Float'])),
        # Use Splittable instead of Object for GWT
        ('object', None):
        ('Splittable',
         ImportDefinition(
             ['com.google.web.bindery.autobean.shared.Splittable'])),
        ('string', None): ('String', ImportDefinition(['java.lang.String'])),
        ('string', 'byte'): ('String', ImportDefinition(['java.lang.String'])),
        # GWT does not support date-time
        ('string', 'date-time'): ('String',
                                  ImportDefinition(['java.lang.String'])),
        ('string', 'int64'): ('Long', ImportDefinition(['java.lang.Long'])),
        # Java does not support Unsigned Integers
        ('string', 'uint64'): ('BigInteger',
                               ImportDefinition(['java.math.BigInteger'])),
    }

    def __init__(self):
        super(GwtLanguageModel, self).__init__()
        self._type_map = GwtLanguageModel.TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS

    def CodeTypeForVoid(self):
        """Return a GWT style void.

    Overrides the default.

    Returns:
      (str) 'Void'
    """
        return 'Void'
Example #6
0
class GwtLanguageModel(java_generator.JavaLanguageModel):
    """A LanguageModel for GWT."""

    language = 'java'

    member_policy = language_model.NamingPolicy(
        language_model.LOWER_CAMEL_CASE)
    getter_policy = language_model.NamingPolicy(
        language_model.UPPER_CAMEL_CASE, 'get{name}')
    setter_policy = language_model.NamingPolicy(
        language_model.UPPER_CAMEL_CASE, 'set{name}')
    constant_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_UNCAMEL_CASE, separator='_')
    array_of_policy = language_model.NamingPolicy(
        format_string='java.util.List<{name}>')
    map_of_policy = language_model.NamingPolicy(
        format_string='java.util.Map<String, {name}>')

    # Dictionary of json type and format to its corresponding import definition.
    # The first import in the imports list is the primary import.
    TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = {
        ('boolean', None):
        ('Boolean', ImportDefinition(['java.lang.Boolean'])),
        # Use String instead of Object for GWT
        ('any', None): ('String', ImportDefinition(['java.lang.String'])),
        ('integer', 'int16'): ('Short', ImportDefinition(['java.lang.Short'])),
        ('integer', 'int32'): ('Integer',
                               ImportDefinition(['java.lang.Integer'])),
        # Java does not support Unsigned Integers
        ('integer', 'uint32'): ('Long', ImportDefinition(['java.lang.Long'])),
        ('number', 'double'):
        ('Double', ImportDefinition(['java.lang.Double'])),
        ('number', 'float'): ('Float', ImportDefinition(['java.lang.Float'])),
        # Use Splittable instead of Object for GWT
        ('object', None):
        ('Splittable',
         ImportDefinition(
             ['com.google.web.bindery.autobean.shared.Splittable'])),
        ('string', None): ('String', ImportDefinition(['java.lang.String'])),
        ('string', 'byte'): ('String', ImportDefinition(['java.lang.String'])),
        # GWT does not support date-time
        ('string', 'date-time'): ('String',
                                  ImportDefinition(['java.lang.String'])),
        ('string', 'int64'): ('Long', ImportDefinition(['java.lang.Long'])),
        # Java does not support Unsigned Integers
        ('string', 'uint64'): ('BigInteger',
                               ImportDefinition(['java.math.BigInteger'])),
    }

    def __init__(self, options=None):
        super(GwtLanguageModel, self).__init__(options=options)
        self._type_map = GwtLanguageModel.TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS

    def CodeTypeForVoid(self):
        """Return a GWT style void.

    Overrides the default.

    Returns:
      (str) 'EmptyResponse'
    """
        # TODO(user): Handle empty responses in a more graceful way. Instead of
        # passing the type to use for empty responses, just signal that an empty
        # response is required, and handle that in the templates.
        return 'EmptyResponse'

    def DefaultContainerPathForOwner(self, module):
        """Overrides the default implementation."""
        return '%s/api/gwt/services' % '/'.join(
            utilities.ReversedDomainComponents(module.owner_domain))