Exemple #1
0
    def testAtSignPolicy(self):
        class TestLanguageModel(language_model.LanguageModel):
            allowed_characters = '#'

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)

        m = TestLanguageModel()

        # An identifier with several bad characters, including one at the end
        # which we expect to strip off.
        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CAMEL_CASE)
        self.assertEquals('Myname', m.ApplyCaseTransform('my@name', p))
        self.assertEquals('Name', m.ApplyCaseTransform('@name', p))

        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CAMEL_CASE,
            atsign_policy=language_model.ATSIGN_STRIP)
        self.assertEquals('Myname', m.ApplyCaseTransform('my@name', p))
        self.assertEquals('Name', m.ApplyCaseTransform('@name', p))

        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CAMEL_CASE,
            atsign_policy=language_model.ATSIGN_BREAK)
        self.assertEquals('MyName', m.ApplyCaseTransform('my@name', p))
        self.assertEquals('Name', m.ApplyCaseTransform('@name', p))
Exemple #2
0
class DartLanguageModel(language_model.LanguageModel):
    """A LanguageModel for Dart."""

    language = 'dart'

    _SCHEMA_TYPE_TO_DART_TYPE = {
        'any': 'core.Object',
        'boolean': 'core.bool',
        'integer': 'core.int',
        'long': 'core.int',
        'number': 'core.double',
        'string': 'core.String',
        'object': 'core.Object',
    }

    _DART_KEYWORDS = [
        'break', 'case', 'catch', 'class', 'const', 'continue', 'default',
        'else', 'extends', 'final', 'finally', 'for', 'in', 'is', 'new',
        'null', 'return', 'static', 'super', 'switch', 'throw', 'try', 'var',
        'void', 'while'
    ]

    # We can not create classes which match a Dart keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _DART_KEYWORDS + _SCHEMA_TYPE_TO_DART_TYPE.values()

    array_of_policy = language_model.NamingPolicy(
        format_string='core.List<{name}>')
    map_of_policy = language_model.NamingPolicy(
        format_string='core.Map<core.String, {name}>')

    def __init__(self):
        super(DartLanguageModel, self).__init__(class_name_delimiter='')

    def GetCodeTypeFromDictionary(self, def_dict):
        """Gets an element's data type from its JSON definition.

    Overrides the default.

    Args:
      def_dict: (dict) The defintion dictionary for this type
    Returns:
      A name suitable for use as a Dart data type
    """
        json_type = def_dict.get('type', 'String')
        native_type = self._SCHEMA_TYPE_TO_DART_TYPE.get(json_type)
        return native_type

    def ToMemberName(self, s, unused_the_api):
        """CamelCase a wire format name into a suitable Dart variable name."""
        candidate = utilities.CamelCase(s)
        candidate = candidate[0].lower() + candidate[1:]
        while candidate in self.RESERVED_CLASS_NAMES:
            candidate += '_'
        return candidate
Exemple #3
0
        class TestLanguageModel(language_model.LanguageModel):
            class_name_policy = language_model.NamingPolicy(
                case_transform=language_model.UPPER_CAMEL_CASE,
                separator='!CLASS!',
                format_string='C {name}')

            constant_policy = language_model.NamingPolicy(
                case_transform=language_model.UPPER_CASE,
                separator='!CONSTANT!',
                format_string='K {name}')

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)
Exemple #4
0
        class TestLanguageModel(language_model.LanguageModel):
            allowed_characters = '#'
            member_policy = language_model.NamingPolicy(
                case_transform=language_model.UPPER_CAMEL_CASE,
                format_string='{api_name}!{parent_name}!{name}')

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)
Exemple #5
0
    def testApplyCaseTransform(self):
        class TestLanguageModel(language_model.LanguageModel):
            allowed_characters = '#'

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)

        m = TestLanguageModel()
        # An identifier with several bad characters, including one at the end
        # which we expect to strip off.
        s = 'I-am -a_tesT@'
        p = language_model.NamingPolicy(
            case_transform=language_model.LOWER_CASE)
        self.assertEquals('iamatest', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.PRESERVE_CASE, separator='_')
        self.assertEquals('I_am_a_tesT', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CASE, separator='_')
        self.assertEquals('I_AM_A_TEST', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.LOWER_CASE, separator='_')
        self.assertEquals('i_am_a_test', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CAMEL_CASE)
        self.assertEquals('IAmATesT', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.LOWER_CAMEL_CASE)
        self.assertEquals('iAmATesT', m.ApplyCaseTransform(s, p))
        p = language_model.NamingPolicy(
            case_transform=language_model.UPPER_CAMEL_CASE)
        s = 'allow#this'
        self.assertEquals('Allow#this', m.ApplyCaseTransform(s, p))
Exemple #6
0
        class TestLanguageModel(language_model.LanguageModel):
            # transform and separator are not used for array of
            array_of_policy = language_model.NamingPolicy(
                case_transform=language_model.UPPER_CAMEL_CASE,
                separator='will not be used',
                format_string='Array[{name}]')

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)
Exemple #7
0
        class TestLanguageModel(language_model.LanguageModel):
            member_policy = language_model.NamingPolicy(
                case_transform=language_model.LOWER_CASE,
                separator='!MEMBER!',
                format_string='M {name}')

            getter_policy = language_model.NamingPolicy(
                case_transform=language_model.LOWER_CAMEL_CASE,
                separator='!GETTER!',
                format_string='G {name}')

            setter_policy = language_model.NamingPolicy(
                case_transform=language_model.UPPER_CAMEL_CASE,
                separator='!SETTER!',
                format_string='S {name}')

            def __init__(self, **kwargs):
                super(TestLanguageModel, self).__init__(**kwargs)
 class MyLanguageModel(language_model.LanguageModel):
   constant_policy = language_model.NamingPolicy(
       case_transform=language_model.UPPER_CAMEL_CASE, separator='|')
Exemple #9
0
class PythonLanguageModel(language_model.LanguageModel):
    """A LanguageModel for Python."""

    language = 'python'

    _SCHEMA_TYPE_TO_PYTHON_TYPE = {
        'any': 'object',
        'array': 'list',
        'boolean': 'bool',
        'integer': 'long',
        'number': 'float',
        'object': 'object',
        'string': 'str',
    }

    _PYTHON_KEYWORDS = discovery_client.RESERVED_WORDS

    # We can not create classes which match a Python keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _PYTHON_KEYWORDS

    array_of_policy = language_model.NamingPolicy(format_string='list')
    map_of_policy = language_model.NamingPolicy(format_string='dict')

    def __init__(self):
        super(PythonLanguageModel, self).__init__(class_name_delimiter='.')

        self._SUPPORTED_TYPES['array'] = self._List
        self._SUPPORTED_TYPES['boolean'] = self._Boolean
        self._SUPPORTED_TYPES['object'] = self._Dictionary

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

    def _Dictionary(self, data_value):
        """Convert provided object to language specific literal."""
        wrapper = '{%s}'
        pairs = []

        for key, val in data_value.value.iteritems():
            val = self.RenderDataValue(val)
            pairs.append('"%s": %s' % (key, val))

        return wrapper % ', '.join(pairs)

    def _List(self, data_value):
        """Convert provided array to language specific literal."""
        wrapper = '[%s]'
        items = [self.RenderDataValue(element) for element in data_value.value]

        return wrapper % ', '.join(items)

    def GetCodeTypeFromDictionary(self, def_dict):
        """Gets an element's data type from its JSON definition.

    Overrides the default.

    Args:
      def_dict: (dict) The definition dictionary for this type
    Returns:
      A name suitable for use as a Python data type
    """
        json_type = def_dict.get('type', 'string')
        native_type = (self._SCHEMA_TYPE_TO_PYTHON_TYPE.get(json_type)
                       or self._SCHEMA_TYPE_TO_PYTHON_TYPE.get('string'))
        return native_type

    # pylint: disable=unused-argument
    def ToMemberName(self, s, the_api):
        """Convert a wire format name into a suitable Python variable name."""
        return s.replace('-', '_')
class SampleLanguageModel(language_model.LanguageModel):
    """A LanguageModel for a sample language."""

    language = 'sample'

    # Set up variable naming policy
    allowed_characters = '_'
    array_of_policy = language_model.NamingPolicy(
        format_string='{module}::Array<{name}>')
    map_of_policy = language_model.NamingPolicy(
        format_string='Map<string, {name}>')
    class_name_policy = language_model.NamingPolicy(
        case_transform=language_model.LOWER_CASE, separator='_')
    constant_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CASE, separator='_')
    member_policy = language_model.NamingPolicy(format_string='_{name}',
                                                separator='_')
    getter_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='get{name}')
    setter_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='set{name}')

    _SCHEMA_TYPE_TO_LANGUAGE_TYPE = {
        'any': 'object',
        'array': 'array',
        'boolean': 'bool',
        'integer': 'long',
        'number': 'float',
        'object': 'object',
        'string': 'str',
    }

    # We can not create classes which match a keyword or built in object type.
    RESERVED_CLASS_NAMES = ['class', 'import', 'return']  # ...

    def __init__(self):
        super(SampleLanguageModel, self).__init__(module_name_delimiter='::')

        self._SUPPORTED_TYPES['array'] = self._List
        self._SUPPORTED_TYPES['boolean'] = self._Boolean
        self._SUPPORTED_TYPES['object'] = self._Dictionary

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

    def _Dictionary(self, data_value):
        """Convert provided object to language specific literal."""
        wrapper = '{%s}'
        pairs = []

        for key, val in data_value.value.iteritems():
            val = self.RenderDataValue(val)
            pairs.append('"%s": %s' % (key, val))

        return wrapper % ', '.join(pairs)

    def _List(self, data_value):
        """Convert provided array to language specific literal."""
        wrapper = '[%s]'
        items = [self.RenderDataValue(element) for element in data_value.value]

        return wrapper % ', '.join(items)

    def GetCodeTypeFromDictionary(self, def_dict):
        """Gets an element's data type from its JSON definition.

    Overrides the default.

    Args:
      def_dict: (dict) The definition dictionary for this type
    Returns:
      A name suitable for use as a data type
    """
        json_type = def_dict.get('type', 'string')
        native_type = (self._SCHEMA_TYPE_TO_LANGUAGE_TYPE.get(json_type)
                       or self._SCHEMA_TYPE_TO_LANGUAGE_TYPE.get('string'))
        return native_type

    def ToMemberName(self, s, unused_api):
        """Convert a wire format name into a suitable variable name."""
        return s.replace('-', '_')
Exemple #11
0
    def AnnotateApi(self, api_object):
        api_object.SetTemplateValue('enums', [])
        name = api_object.values['canonicalName']
        api_name_policy = language_model.NamingPolicy(
            language_model.UPPER_CAMEL_CASE)
        camel_case_name = self._language_model.TransformString(
            api_object, name, api_name_policy)
        api_object.SetTemplateValue('serviceName',
                                    'GTLService%s' % (camel_case_name))
        rpc_url = api_object.GetTemplateValue('rpcUrl')
        if rpc_url:
            rpc_url += '?prettyPrint=false'
            api_object.SetTemplateValue('rpcUrl', rpc_url)
            # Only generate query class for RPC discovery documents, not REST.
            api_object.SetTemplateValue('query',
                                        'GTLQuery%s' % (camel_case_name))

        api_object.SetTemplateValue('parameters', [
            param for param in api_object.GetTemplateValue('parameters')
            if param.GetTemplateValue('wireName') not in
            self._COMMON_PARAMS_TO_SKIP
        ])

        super(ObjCGenerator, self).AnnotateApi(api_object)

        # Collect all method parameters for combined query class.
        # The query class has properties for all method parameters on the API, with
        # a static method for each API method to generate the appropriate query
        # object. There are likely to be naming clashes where two or more API
        # methods have parameters of the same name but different types. When this
        # happens, we use the 'id' type instead.
        method_parameters = {}
        for method in api_object.GetTemplateValue('methods'):
            for parameter in method.parameters:
                # Check for duplicate
                existing_parameter = method_parameters.get(parameter.codeName)
                if not existing_parameter:
                    method_parameters[parameter.codeName] = parameter
                elif existing_parameter.codeType != parameter.codeType:
                    # Duplicate exists with mismatched type; synthesise new parameter
                    # using 'id' type instead.
                    merged_param = api.Parameter(
                        api_object, parameter.GetTemplateValue('wireName'), {
                            'description':
                            '"%s" has different types for some query methods; see the '
                            'documentation for the right type for each query method.'
                            % (parameter.codeName),
                            'wireName':
                            parameter['wireName'],
                            'codeName':
                            parameter.codeName,
                        }, existing_parameter.parent)
                    merged_param.SetTemplateValue('codeType', 'id')
                    merged_param.SetTemplateValue('attributes',
                                                  'nonatomic, retain')
                    merged_param.SetTemplateValue('noPointer', True)
                    method_parameters[parameter.codeName] = merged_param
        api_object.SetTemplateValue(
            'methodParameters',
            [method_parameters[key] for key in sorted(method_parameters)])

        # Also build a sorted list of all parameters, both common and per-method
        all_parameters = method_parameters.copy()
        for parameter in api_object.GetTemplateValue('parameters'):
            all_parameters[parameter.codeName] = parameter
        api_object.SetTemplateValue(
            'allParameters',
            [all_parameters[key] for key in sorted(all_parameters)])
Exemple #12
0
class ObjCLanguageModel(language_model.LanguageModel):
    """A LanguageModel for Objective-C."""

    array_of_policy = language_model.NamingPolicy(format_string='NSArray')
    map_of_policy = language_model.NamingPolicy(format_string='NSDictionary')
    constant_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='k{schema.className}_{variable_name}_{name}')
    query_method_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='queryFor{name}')

    _SCHEMA_TYPE_TO_OBJC_TYPE = {
        ('any', None): 'String',
        ('boolean', None): 'NSNumber',
        ('integer', None): 'NSNumber',
        ('integer', 'int16'): 'NSNumber',
        ('integer', 'uint16'): 'NSNumber',
        ('integer', 'int32'): 'NSNumber',
        ('integer', 'uint32'): 'NSNumber',
        ('number', None): 'NSNumber',
        ('number', 'double'): 'NSNumber',
        ('number', 'float'): 'NSNumber',
        ('object', None): 'GTLObject',
        ('string', None): 'NSString',
        ('string', 'byte'): 'NSString',
        ('string', 'date'): 'NSString',
        ('string', 'date-time'): 'GTLDateTime',
        ('string', 'int64'): 'NSNumber',
        ('string', 'uint64'): 'NSNumber',
    }

    # http://www.binpress.com/tutorial/objective-c-reserved-keywords/43
    _OBJC_KEYWORDS = [
        'asm',
        'auto',
        'break',
        'case',
        'char',
        'const',
        'continue',
        'default',
        'do',
        'double',
        'else',
        'enum',
        'extern',
        'float',
        'for',
        'goto',
        'if',
        'inline',
        'int',
        'long',
        'register',
        'restrict',
        'return',
        'short',
        'signed',
        'sizeof',
        'static',
        'struct',
        'switch',
        'typedef',
        'union',
        'unsigned',
        'void',
        'volatile',
        'while',
        '_Bool',
        '_Complex',
        '_Imaginary',
    ]
    # C/C++ keywords (including C99 and C++ 0x11)
    _CPP_KEYWORDS = [
        'and',
        'alignas',
        'alignof',
        'bitand',
        'bitor',
        'bool',
        'catch',
        'compl',
        'constexpr',
        'decltype',
        'default',
        'delete',
        'explicit',
        'export',
        'false',
        'friend',
        'mutable',
        'namespace',
        'new',
        'noexcept',
        'not',
        'nullptr',
        'operator',
        'or',
        'private',
        'protected',
        'public',
        'template',
        'this',
        'throw',
        'true',
        'try',
        'typeid',
        'typename',
        'using',
        'virtual',
        'xor',
        'restrict',
    ]
    _NAMES_TO_AVOID = [
        'bool',
        'bycopy',
        'byref',
        'class',
        'id',
        'imp',
        'in',
        'inout',
        'nil',
        'no',
        'null',
        'object',
        'oneway',
        'out',
        'protocol',
        'sel',
        'self',
        'string',
        'super',
        'yes',
        'atomic',
        'nonatomic',
        'retain',
    ]

    # We can not create classes which match a ObjC keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _OBJC_KEYWORDS + _CPP_KEYWORDS + _NAMES_TO_AVOID

    # We can not create data members which are in NSObject or GTLObject.
    RESERVED_MEMBER_NAMES = RESERVED_CLASS_NAMES + [
        # NSObject methods
        'description',
        'debugDescription',
        'finalize',
        'hash',
        'dealloc',
        'init',
        'superclass',
        'retain',
        'release',
        'autorelease',
        'retainCount',
        'zone',
        'isProxy',
        'classForCoder',
        # Foundation protocol methods
        'copy',
        'copyWithZone',
        'mutableCopy',
        'mutableCopyWithZone',
        # GTLObject methods
        'JSON',
        'JSONString',
        'surrogates',
        'userProperties',
        'additionalJSONKeys',
        'additionalProperties',
        'userData',
        'fieldsDescription',
    ]
    reserved_words = RESERVED_MEMBER_NAMES

    def __init__(self, options=None):
        super(ObjCLanguageModel, self).__init__()
        self._options = options

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json primitive type to a suitable ObjC 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')
        native_format = self._SCHEMA_TYPE_TO_OBJC_TYPE.get(
            (json_type, json_format), json_type)
        return native_format

    def ToMemberName(self, s, unused_api):
        """Convert a wire format name into a suitable ObjC variable name."""
        if s.lower() == 'id':  # Special case for id
            return 'identifier'
        camel_s = utilities.CamelCase(s)
        ret = camel_s[0].lower() + camel_s[1:]
        if s.lower() in ObjCLanguageModel.RESERVED_MEMBER_NAMES:
            ret = '%sProperty' % ret
        return ret

    def DefaultContainerPathForOwner(self, module):
        return '/'.join(utilities.ReversedDomainComponents(
            module.owner_domain))
Exemple #13
0
class CSharpLanguageModel(language_model.LanguageModel):
  """A LanguageModel for C#."""

  language = 'csharp'

  # Allowed '<>' for the usage of Nullable<xxx>
  # Allowed ',' to enable it in a dictionary
  allowed_characters = '<>,'

  # Set up variable naming policy
  array_of_policy = language_model.NamingPolicy(
      format_string='System.Collections.Generic.IList<{name}>')
  map_of_policy = language_model.NamingPolicy(
      format_string='System.Collections.Generic.IDictionary<string, {name}>')
  constant_policy = language_model.NamingPolicy(
      case_transform=language_model.UPPER_CAMEL_CASE)
  class_name_policy = language_model.NamingPolicy(
      case_transform=language_model.UPPER_CAMEL_CASE, separator='.')
  member_policy = language_model.NamingPolicy(
      case_transform=language_model.UPPER_CAMEL_CASE)

  # TODO(user): Fix these 3 tables
  _SCHEMA_TYPE_TO_CSHARP_TYPE = {
      ('any', None): 'object',
      ('boolean', None): 'System.Nullable<bool>',
      ('integer', None): 'System.Nullable<int>',
      ('number', None): 'System.Nullable<double>',
      ('integer', 'int16'): 'System.Nullable<short>',
      ('integer', 'int32'): 'System.Nullable<int>',
      ('integer', 'uint32'): 'System.Nullable<long>',
      ('number', 'double'): 'System.Nullable<double>',
      ('number', 'float'): 'System.Nullable<float>',
      ('string', None): 'string',
      ('string', 'byte'): 'string',
      ('string', 'date'): 'string',  # Date only in 'yyyy-mm-dd' format
      ('string', 'date-time'): 'System.Nullable<System.DateTime>',
      ('string', 'int64'): 'System.Nullable<long>',
      ('string', 'uint64'): 'System.Nullable<ulong>',
      ('object', None): 'object',
      }

  _CSHARP_KEYWORDS = [
      'abstract', 'as', 'base', 'bool', 'break', 'byte', 'case', 'catch',
      'char', 'checked', 'class', 'const', 'continue', 'decimal', 'default',
      'delegate', 'do', 'double', 'else', 'enum', 'event', 'explicit', 'extern',
      'false', 'finally', 'fixed', 'float', 'for', 'foreach', 'goto', 'if',
      'implicit', 'in', 'int', 'interface', 'internal', 'is', 'lock', 'long',
      'namespace', 'new', 'null', 'object', 'operator', 'out', 'override',
      'params', 'private', 'protected', 'public', 'readonly', 'ref', 'return',
      'sbyte', 'sealed', 'short', 'sizeof', 'stackalloc', 'static', 'string',
      'struct', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'uint',
      'ulong', 'unchecked', 'unsafe', 'ushort', 'using', 'virtual', 'void',
      'volatile', 'while', 'async', 'await'
      ]

  RESERVED_CLASS_NAMES = _CSHARP_KEYWORDS
  reserved_words = RESERVED_CLASS_NAMES

  def __init__(self):
    super(CSharpLanguageModel, self).__init__(class_name_delimiter='.')

  def GetCodeTypeFromDictionary(self, def_dict):
    """Gets an element's data type from its JSON definition.

    Overrides the default.

    Args:
      def_dict: (dict) The defintion dictionary for this type
    Returns:
      A name suitable for use as a C# data type
    """
    json_type = def_dict.get('type', 'string')
    json_format = def_dict.get('format')
    native_type = self._SCHEMA_TYPE_TO_CSHARP_TYPE.get((json_type, json_format))
    if not native_type:
      native_type = 'object'
    return native_type

  def ApplyPolicy(self, policy_name, variable, value):
    """Override the default policy applier so we can do special things."""

    # We need to look for class members clashing with the name of the container.
    # TODO(user): This begs for having a more extensible conflict policy
    # mechanism in LanguageModel.
    if policy_name == 'member':
      return self.ToClassMemberName(variable, value)
    return super(CSharpLanguageModel, self).ApplyPolicy(policy_name, variable,
                                                        value)

  def ToClassMemberName(self, variable, name):
    formatted = super(CSharpLanguageModel, self).ApplyPolicy('member', variable,
                                                             name)
    if isinstance(variable, schema.Property):
      if variable.schema.values.get('className') == formatted:
        formatted += 'Value'
    return formatted

  def ToMemberName(self, s, the_api):
    """CamelCase a wire format name into a suitable C# variable name."""
    camel_s = utilities.CamelCase(s)
    if s in self.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 DefaultContainerPathForOwner(self, module):
    """Returns the default path for the module containing this API."""
    return '%s/Apis' % utilities.CamelCase(module.owner_name)

  def ToSafeClassName(self, name, the_api, parent):  # pylint:disable=unused-argument
    # Retrieve the object in question.
    if parent:
      for child in parent.children:
        if child.get('wireName') == name:
          return child.className.split('.')[-1]
    # Fall through if it cannot be found
    if parent:
      name += '_data'
    return utilities.CamelCase(name)
class ObjCLanguageModel(language_model.LanguageModel):
    """A LanguageModel for Objective-C."""

    array_of_policy = language_model.NamingPolicy(format_string='NSArray')
    map_of_policy = language_model.NamingPolicy(format_string='NSDictionary')
    constant_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='k{className}_{propertyName}_{name}')
    query_method_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='queryFor{name}')

    _SCHEMA_TYPE_TO_OBJC_TYPE = {
        ('any', None): 'String',
        ('boolean', None): 'NSNumber',
        ('integer', None): 'NSNumber',
        ('integer', 'int16'): 'NSNumber',
        ('integer', 'uint16'): 'NSNumber',
        ('integer', 'int32'): 'NSNumber',
        ('integer', 'uint32'): 'NSNumber',
        ('number', None): 'NSNumber',
        ('number', 'double'): 'NSNumber',
        ('number', 'float'): 'NSNumber',
        ('object', None): 'GTLObject',
        ('string', None): 'NSString',
        ('string', 'byte'): 'NSString',
        ('string', 'date'): 'NSString',
        ('string', 'date-time'): 'NSString',
        ('string', 'int64'): 'NSNumber',
        ('string', 'uint64'): 'NSNumber',
    }

    # http://www.binpress.com/tutorial/objective-c-reserved-keywords/43
    _OBJC_KEYWORDS = [
        'asm',
        'auto',
        'break',
        'case',
        'char',
        'const',
        'continue',
        'default',
        'do',
        'double',
        'else',
        'enum',
        'extern',
        'float',
        'for',
        'goto',
        'if',
        'inline',
        'int',
        'long',
        'register',
        'restrict',
        'return',
        'short',
        'signed',
        'sizeof',
        'static',
        'struct',
        'switch',
        'typedef',
        'union',
        'unsigned',
        'void',
        'volatile',
        'while',
        '_Bool',
        '_Complex',
        '_Imaginary',
    ]
    _NAMES_TO_AVOID = [
        'bool',
        'bycopy',
        'byref',
        'class',
        'id',
        'imp',
        'in',
        'inout',
        'nil',
        'no',
        'null',
        'object',
        'oneway',
        'out',
        'protocol',
        'sel',
        'self',
        'string',
        'super',
        'yes',
        'atomic',
        'nonatomic',
        'retain',
    ]

    # These names were things we had reserved in the past. It might be overly
    # broad
    _MORE_NAMES_TO_AVOID = [
        'any',
        'boolean',
        'integer',
        'namespace',
        'number',
        'true',
        'false',
    ]

    # We can not create classes which match a ObjC keyword or built in object
    # type.
    RESERVED_CLASS_NAMES = _OBJC_KEYWORDS + _NAMES_TO_AVOID + _MORE_NAMES_TO_AVOID

    # We can not create data members which are in GTLObject.
    RESERVED_MEMBER_NAMES = RESERVED_CLASS_NAMES + ['description', 'id']
    reserved_words = RESERVED_MEMBER_NAMES

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json primitive type to a suitable ObjC 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')
        native_format = self._SCHEMA_TYPE_TO_OBJC_TYPE.get(
            (json_type, json_format), json_type)
        return native_format

    def ToMemberName(self, s, unused_api):
        """Convert a wire format name into a suitable ObjC variable name."""
        if s.lower() == 'id':  # Special case for id
            return 'identifier'
        camel_s = utilities.CamelCase(s)
        ret = camel_s[0].lower() + camel_s[1:]
        if s.lower() in ObjCLanguageModel.RESERVED_MEMBER_NAMES:
            ret = '%sProperty' % ret
        return ret

    def DefaultContainerPathForOwner(self, module):
        path = module.owner_name.lower()
        if module.owner_domain == 'google.com' and not module.package_path:
            path += '/api/services'
        return path
class CppLanguageModel(language_model.LanguageModel):
    """A LanguageModel tuned for C++."""

    language = 'cpp'
    member_policy = language_model.NamingPolicy(
        language_model.LOWER_UNCAMEL_CASE, '{name}_', '_')
    getter_policy = language_model.NamingPolicy(
        language_model.LOWER_UNCAMEL_CASE, 'get_{name}', '_')
    setter_policy = language_model.NamingPolicy(
        language_model.LOWER_UNCAMEL_CASE, 'set_{name}', '_')
    has_policy = language_model.NamingPolicy(language_model.LOWER_UNCAMEL_CASE,
                                             'has_{name}', '_')
    unset_policy = language_model.NamingPolicy(
        language_model.LOWER_UNCAMEL_CASE, 'clear_{name}', '_')

    parameter_name_policy = language_model.NamingPolicy(
        language_model.LOWER_UNCAMEL_CASE,
        '{name}',
        '_',
        conflict_policy=language_model.NamingPolicy(
            language_model.LOWER_UNCAMEL_CASE, '{name}__', '_'))

    # From http://en.cppreference.com/w/cpp/keyword
    _CPP_KEYWORDS = [
        'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand',
        'bitor', 'bool', 'break', 'case', 'catch', 'char', 'char16_t',
        'char32_t', 'class', 'compl', 'const', 'constexpr', 'const_cast',
        'continue', 'decltype', 'default', 'delete', 'do', 'double',
        'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern',
        'false', 'float', 'for', 'friend', 'goto', 'if', 'inline', 'int',
        'long', 'mutable', 'namespace', 'new', 'noexcept', 'not', 'not_eq',
        'nullptr', 'operator', 'or', 'or_eq', 'private', 'protected', 'public',
        'register', 'reinterpret_cast', 'return', 'short', 'signed', 'sizeof',
        'static', 'static_assert', 'static_cast', 'struct', 'switch',
        'template', 'this', 'thread_local', 'throw', 'true', 'try', 'typedef',
        'typeid', 'typename', 'union', 'unsigned', 'using', 'virtual', 'void',
        'volatile', 'wchar_t', 'while', 'xor', 'xor_eq'
    ]

    _SPECIAL_CLASS_NAMES = ['JsonCppData', 'SerializableJson']

    # We can not create classes which match a C++ keyword or built in object
    # type or keyword. However since:
    #   * class names are case-sensitive
    #   * we'll always generate camel-case names (or least starting upper case)
    #   * no C++ keywords are uppercase
    # We only have to worry about classes built into the generator itself.
    # And really we do not need to even do that since they are in a different
    # namespace. But we will for convenience and since it's probably rare.
    RESERVED_CLASS_NAMES = _SPECIAL_CLASS_NAMES

    reserved_words = RESERVED_CLASS_NAMES + _CPP_KEYWORDS

    def __init__(self, options=None):
        super(CppLanguageModel, self).__init__(class_name_delimiter='::',
                                               module_name_delimiter='_')
        self.type_map = self._BuildTypeMap(options)

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

    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])),
        }

    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 = {
            'int16': '%s',
            'uint16': '%s',
            'int32': '%s',
            'uint32': '%s',
            'int64': '%sL',
            'uint64': '%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 C++ '
                 'annotated code type (%s).') %
                (data_value.value, data_value.code_type))

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json schema type to a suitable C++ 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 ArrayOf(self, unused_variable, type_name):
        """Take a type name and return the syntax for an array of them.

    Overrides the default.

    Args:
      unused_variable: (DataType) the data we want an array of.
      type_name: (str) A type name.
    Returns:
      A language specific string meaning "an array of type_name".
    """
        # TODO(user): 20120817
        # Need to figure out whether the type is a primitive or not, then
        # return appropriate array type (data, string or primitive).
        return '%s::JsonCppArray<%s >' % (self.client_namespace_, type_name)

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

    Overrides the default.

    Args:
      unused_variable: (DataType) the data we want an array of.
      type_name: (str) A type name.
    Returns:
      A language specific string meaning "an array of type_name".
    """
        return '%s::JsonCppAssociativeArray<%s >' % (self.client_namespace_,
                                                     type_name)

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

    # pylint: disable=unused-argument
    def ToSafeClassName(self, s, the_api, parent=None):
        """Convert a name to a suitable class name in C++.

    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 C++.
    """
        safe_class_name = utilities.CamelCase(s)
        if parent:
            for ancestor in parent.full_path:
                if ancestor.class_name == safe_class_name:
                    safe_class_name = '%s%s' % (parent.class_name,
                                                safe_class_name)
        if safe_class_name.lower() in CppLanguageModel.RESERVED_CLASS_NAMES:
            # Prepend the service name
            safe_class_name = '%s%s' % (utilities.CamelCase(
                the_api.values['name']), utilities.CamelCase(s))
        return safe_class_name

    def DefaultContainerPathForOwner(self, module):
        """Overrides the default implementation."""
        result = ''
        if FLAGS.cpp_generator_add_owner_dir:
            result = module.owner_name.lower().replace(' ', '_')
        return result
Exemple #16
0
class PhpLanguageModel(language_model.LanguageModel):
    """A LanguageModel tunded for PHP."""

    language = 'php'

    _SCHEMA_TYPE_TO_PHP_TYPE = {
        'any': 'array',
        'boolean': 'bool',
        'integer': 'int',
        'long': 'string',  # PHP doesn't support long integers.
        'number': 'double',
        'string': 'string',
        'uint32': 'string',  # PHP doesn't support unsigned integers.
        'uint64': 'string',  # PHP doesn't support unsigned integers.
        'int32': 'int',
        'int64': 'string',  # Size of an integer is platform-dependent.
        'double': 'double',
        'float': 'float',
    }

    # Populated from http://php.net/manual/en/reserved.keywords.php
    PHP_KEYWORDS = frozenset((
        'abstract',
        'and',
        'array',
        'as',
        'break',
        'call',
        'callable',
        'case',
        'catch',
        'cfunction',
        'class',
        'clone',
        'const',
        'continue',
        'declare',
        'default',
        'do',
        'else',
        'elseif',
        'empty',
        'enddeclare',
        'endfor',
        'endforeach',
        'endif',
        'endswitch',
        'endwhile',
        'extends',
        'final',
        'finally',
        'for',
        'foreach',
        'function',
        'global',
        'goto',
        'if',
        'implements',
        'interface',
        'instanceof',
        'list',
        'namespace',
        'new',
        'old_function',
        'or',
        'parent',
        'private',
        'protected',
        'public',
        'return',
        'static',
        'switch',
        'throw',
        'trait',
        'try',
        'unset',
        'use',
        'var',
        'while',
        'xor',
        'yield',
    ))

    PHP_TYPES = frozenset((
        'bool',
        'boolean',
        'int',
        'integer',
        'file',
        'float',
        'double',
        'string',
        'array',
        'object',
        'null',
        'resource',
    ))

    # We can not create classes which match a PHP keyword or built in object type.
    RESERVED_CLASS_NAMES = PHP_KEYWORDS | PHP_TYPES

    array_of_policy = language_model.NamingPolicy(format_string='{name}')
    map_of_policy = language_model.NamingPolicy(format_string='{name}')
    member_policy = language_model.NamingPolicy(
        case_transform=language_model.LOWER_CAMEL_CASE)
    getter_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='get{name}')
    setter_policy = language_model.NamingPolicy(
        case_transform=language_model.UPPER_CAMEL_CASE,
        format_string='set{name}')

    def __init__(self):
        super(PhpLanguageModel, self).__init__(class_name_delimiter='.')

    def GetCodeTypeFromDictionary(self, def_dict):
        """Convert a json primitive type to a suitable PHP 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 PHP.
    """

        # Unique identifier for this schema.
        json_type = def_dict.get('type', 'string')

        # An additional regular expression or key that helps constrain the value.
        # See: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23
        json_format = def_dict.get('format')

        # If we know what to do with this format type, then use native type.
        php_type = (self._SCHEMA_TYPE_TO_PHP_TYPE.get(json_format)
                    or self._SCHEMA_TYPE_TO_PHP_TYPE.get(json_type, json_type))
        return php_type

    def ToMemberName(self, s, unused_api):
        """Convert a wire format name into a suitable PHP variable name.

    Overrides the default.

    Args:
      s: (string) The wire format name of a member variable.
    Returns:
      A name suitable for use as a member in PHP.
    """
        return s.replace('-', '_').replace('.', '_').replace('/', '__')
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))
Exemple #18
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))