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