diff --git a/tools/abstractapi.py b/tools/abstractapi.py index 0956b2cbf..bbf95dfa1 100644 --- a/tools/abstractapi.py +++ b/tools/abstractapi.py @@ -110,11 +110,13 @@ class Object(object): def __lt__(self, other): return self.name < other.name - def find_first_ancestor_by_type(self, *types): + def find_first_ancestor_by_type(self, *types, priorAncestor=False): + current = self ancestor = self.parent while ancestor is not None and type(ancestor) not in types: + current = ancestor ancestor = ancestor.parent - return ancestor + return ancestor if not priorAncestor else current class Type(Object): @@ -159,14 +161,14 @@ class ListType(Type): self.containedTypeName = containedTypeName self._containedTypeDesc = None - def _set_contained_type_desc(self, desc): - self._containedTypeDesc = desc - desc.parent = self - - def _get_contained_type_desc(self): + @property + def containedTypeDesc(self): return self._containedTypeDesc - containedTypeDesc = property(fset=_set_contained_type_desc, fget=_get_contained_type_desc) + @containedTypeDesc.setter + def containedTypeDesc(self, desc): + self._containedTypeDesc = desc + desc.parent = self def translate(self, translator, **params): return translator.translate_list_type(self, **params) @@ -177,25 +179,25 @@ class DocumentableObject(Object): Object.__init__(self, name) self._briefDescription = None self._detailedDescription = None - self.deprecated = None - def _get_brief_description(self): + @property + def briefDescription(self): return self._briefDescription - def _set_brief_description(self, description): + @briefDescription.setter + def briefDescription(self, description): self._briefDescription = description description.relatedObject = self - def _get_detailed_description(self): + @property + def detailedDescription(self): return self._detailedDescription - def _set_detailed_description(self, description): + @detailedDescription.setter + def detailedDescription(self, description): self._detailedDescription = description description.relatedObject = self - briefDescription = property(fget=_get_brief_description, fset=_set_brief_description) - detailedDescription = property(fget=_get_detailed_description, fset=_set_detailed_description) - def set_from_c(self, cObject, namespace=None): self.briefDescription = cObject.briefDescription self.detailedDescription = cObject.detailedDescription @@ -214,11 +216,45 @@ class DocumentableObject(Object): class Namespace(DocumentableObject): def __init__(self, name): DocumentableObject.__init__(self, name) - self.children = [] + self.enums = [] + self.classes = [] + self.interfaces = [] + + def addenum(self, enum): + Namespace._insert_element(self.enums, enum) + enum.parent = self + + def delenum(self, enum): + i = self.enums.index(enum) + del self.enums[i] + enum.parent = None + + def addclass(self, class_): + Namespace._insert_element(self.classes, class_) + class_.parent = self + + def delclass(self, class_): + i = self.classes.index(class_) + del self.classes[i] + class_.parent = None - def add_child(self, child): - self.children.append(child) - child.parent = self + def addinterface(self, interface): + Namespace._insert_element(self.interfaces, interface) + interface.parent = self + + def delinterface(self, interface): + i = self.interfaces.index(interface) + del self.interfaces[i] + interface.parent = None + + @staticmethod + def _insert_element(l, e): + try: + inspoint = next(x for x in l if e.name < x.name) + index = l.index(inspoint) + l.insert(index, e) + except StopIteration: + l.append(e) GlobalNs = Namespace('') @@ -280,14 +316,14 @@ class Argument(DocumentableObject): self.optional = optional self.default = default - def _set_type(self, _type): - self._type = _type - _type.parent = self - - def _get_type(self): + @property + def type(self): return self._type - type = property(fset=_set_type, fget=_get_type) + @type.setter + def type(self, _type): + self._type = _type + _type.parent = self def translate(self, translator, **params): return translator.translate_argument(self, **params) @@ -309,14 +345,14 @@ class Method(DocumentableObject): self.args.append(arg) arg.parent = self - def _set_return_type(self, returnType): - self._returnType = returnType - returnType.parent = self - - def _get_return_type(self): + @property + def returnType(self): return self._returnType - returnType = property(fset=_set_return_type, fget=_get_return_type) + @returnType.setter + def returnType(self, returnType): + self._returnType = returnType + returnType.parent = self def translate_as_prototype(self, translator, **params): return translator.translate_method_as_prototype(self, **params) @@ -329,56 +365,57 @@ class Property(DocumentableObject): self._getter = None self._type = None - def set_setter(self, setter): + @property + def setter(self): + return self._setter + + @setter.setter + def setter(self, setter): self._setter = setter setter.parent = self - def get_setter(self): - return self._setter + @property + def getter(self): + return self._getter - def set_getter(self, getter): + @getter.setter + def getter(self, getter): self._getter = getter if self._type is None: self._type = getter.returnType getter.parent = self - - def get_getter(self): - return self._getter - - setter = property(fset=set_setter, fget=get_setter) - getter = property(fset=set_getter, fget=get_getter) -class Class(DocumentableObject): +class Class(Namespace): def __init__(self, name): - DocumentableObject.__init__(self, name) + Namespace.__init__(self, name) self.properties = [] self.instanceMethods = [] self.classMethods = [] self._listenerInterface = None self.multilistener = False self.refcountable = False - + def add_property(self, property): - self.properties.append(property) + Namespace._insert_element(self.properties, property) property.parent = self def add_instance_method(self, method): - self.instanceMethods.append(method) + Namespace._insert_element(self.instanceMethods, method) method.parent = self def add_class_method(self, method): - self.classMethods.append(method) + Namespace._insert_element(self.classMethods, method) method.parent = self - def set_listener_interface(self, interface): - self._listenerInterface = interface - interface._listenedClass = self - - def get_listener_interface(self): + @property + def listenerInterface(self): return self._listenerInterface - listenerInterface = property(fget=get_listener_interface, fset=set_listener_interface) + @listenerInterface.setter + def listenerInterface(self, interface): + self._listenerInterface = interface + interface._listenedClass = self def sort(self): self.properties.sort() @@ -396,10 +433,14 @@ class Interface(DocumentableObject): self.methods.append(method) method.parent = self - def get_listened_class(self): + @property + def listenedClass(self): return self._listenedClass - listenedClass = property(fget=get_listened_class) + @listenedClass.setter + def listenedClass(self, method): + self.methods.append(method) + method.parent = self def sort(self): self.methods.sort() @@ -426,10 +467,34 @@ class CParser(object): # they are no ref()/unref() methods self.forcedRefcountableClasses = ['LinphoneFactory'] + self.enum_relocations = { + 'LinphoneAccountCreatorActivationCodeStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorDomainStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorEmailStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorLanguageStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorPasswordStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorPhoneNumberStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorTransportStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorUsernameStatus' : 'LinphoneAccountCreator', + 'LinphoneCallDir' : 'LinphoneCall', + 'LinphoneCallState' : 'LinphoneCall', + 'LinphoneCallStatus' : 'LinphoneCall', + 'LinphoneChatRoomState' : 'LinphoneChatRoom', + 'LinphoneChatMessageDirection' : 'LinphoneChatMessage', + 'LinphoneChatMessageState' : 'LinphoneChatMessage', + 'LinphoneCoreLogCollectionUploadState' : 'LinphoneCore', + 'LinphoneEventLogType' : 'LinphoneEventLog', + 'LinphoneFriendListStatus' : 'LinphoneFriendList', + 'LinphoneFriendListSyncStatus' : 'LinphoneFriendList', + 'LinphonePlayerState' : 'LinphonePlayer', + 'LinphonePresenceActivityType' : 'LinphonePresenceActivity', + 'LinphoneTunnelMode' : 'LinphoneTunnel' + } + self.cProject = cProject self.enumsIndex = {} - self.enums = [] for enum in self.cProject.enums: if enum.associatedTypedef is None: self.enumsIndex[enum.name] = None @@ -438,8 +503,6 @@ class CParser(object): self.classesIndex = {} self.interfacesIndex = {} - self.classes = [] - self.interfaces = [] for _class in self.cProject.classes: if _class.name not in self.classBl: if _class.name.endswith('Cbs'): @@ -463,6 +526,7 @@ class CParser(object): name.from_snake_case('linphone') self.namespace = Namespace(name) + self._pending_enums = [] def _is_blacklisted(self, name): if type(name) is metaname.MethodName: @@ -485,11 +549,25 @@ class CParser(object): except BlacklistedSymbolError as e: logger.debug(e) + self._treat_pending_enums() self._clean_all_indexes() - self._sortall() self._fix_all_types() self._fix_all_docs() + def _treat_pending_enums(self): + for enum in self._pending_enums: + try: + enum_cname = enum.name.to_c() + parent_cname = self.enum_relocations[enum_cname] + newparent = self.classesIndex[parent_cname] + enum.parent.delenum(enum) + newparent.addenum(enum) + enum.name.from_c(enum_cname, namespace=newparent.name) + except KeyError: + reason = "cannot move the enum inside {0} enum because it doesn't exsist".format(parent_cname) + raise ParsingError(reason, context=enum.name) + self._pending_enums = [] + def _clean_all_indexes(self): for index in [self.classesIndex, self.interfacesIndex, self.methodsIndex]: self._clean_index(index) @@ -503,15 +581,6 @@ class CParser(object): for key in keysToRemove: del index[key] - def _sortall(self): - self.enums.sort() - self.classes.sort() - self.interfaces.sort() - for class_ in self.classes: - class_.sort() - for interface in self.interfaces: - interface.sort() - def _class_is_refcountable(self, _class): if _class.name in self.forcedRefcountableClasses: return True @@ -599,7 +668,7 @@ class CParser(object): enum = Enum(name) enum.briefDescription = cenum.briefDoc enum.detailedDescription = cenum.detailedDoc - self.namespace.add_child(enum) + self.namespace.addenum(enum) for cEnumValue in cenum.values: valueName = metaname.EnumeratorName() @@ -618,7 +687,8 @@ class CParser(object): enum.add_enumerator(aEnumValue) self.enumsIndex[cenum.publicName] = enum - self.enums.append(enum) + if cenum.publicName in self.enum_relocations: + self._pending_enums.append(enum) return enum def parse_class(self, cclass): @@ -630,12 +700,11 @@ class CParser(object): if cclass.name.endswith('Cbs'): _class = self._parse_listener(cclass) self.interfacesIndex[cclass.name] = _class - self.interfaces.append(_class) + self.namespace.addinterface(_class) else: _class = self._parse_class(cclass) self.classesIndex[cclass.name] = _class - self.classes.append(_class) - self.namespace.add_child(_class) + self.namespace.addclass(_class) return _class def _parse_class(self, cclass): @@ -859,6 +928,7 @@ class CParser(object): raise ParsingError('could not find type in \'{0}\''.format(cDecl)) + class Translator: instances = {} @@ -874,6 +944,16 @@ class Translator: except KeyError: raise ValueError("Invalid language code: '{0}'".format(langCode)) + def _get_object_name(self, obj): + return obj.desc.name if isinstance(obj, (EnumType, ClassType)) else obj.name + + def _compute_namespace_name(self, namespace, obj): + if namespace is not None: + return namespace.name if namespace is not GlobalNs else None + else: + namespace = obj.find_first_ancestor_by_type(Enum, Class, Namespace, Interface) + return metaname.Name.find_common_parent(self._get_object_name(obj), namespace.name) + class CLikeLangTranslator(Translator): def translate_enumerator_value(self, value): @@ -1000,37 +1080,22 @@ class CppLangTranslator(CLikeLangTranslator): res += ' *' return res - def translate_enum_type(self, _type, showStdNs=True, namespace=None): - if _type.desc is None: - raise TranslationError('{0} has not been fixed'.format(_type.name)) + def translate_enum_type(self, type_, showStdNs=True, namespace=None): + if type_.desc is None: + raise TranslationError('{0} has not been fixed'.format(type_.name)) + nsName = self._compute_namespace_name(namespace, type_) + return type_.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) + + def translate_class_type(self, type_, showStdNs=True, namespace=None): + if type_.desc is None: + raise TranslationError('{0} has not been fixed'.format(type_.name)) + nsName = self._compute_namespace_name(namespace, type_) + res = type_.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) - if namespace is not None: - nsName = namespace.name if namespace is not GlobalNs else None - else: - method = _type.find_first_ancestor_by_type(Method) - nsName = metaname.Name.find_common_parent(_type.desc.name, method.name) - - return _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) - - def translate_class_type(self, _type, showStdNs=True, namespace=None): - if _type.desc is None: - raise TranslationError('{0} has not been fixed'.format(_type.name)) - - if namespace is not None: - nsName = namespace.name if namespace is not GlobalNs else None - else: - method = _type.find_first_ancestor_by_type(Method) - nsName = metaname.Name.find_common_parent(_type.desc.name, method.name) - - if _type.desc.name.to_c() in self.ambigousTypes: - nsName = None - - res = _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) - - if _type.desc.refcountable: - if _type.isconst: + if type_.desc.refcountable: + if type_.isconst: res = 'const ' + res - if type(_type.parent) is Argument: + if type(type_.parent) is Argument: return 'const {0}<{1}> &'.format( CppLangTranslator.prepend_std('shared_ptr', showStdNs), res @@ -1041,7 +1106,7 @@ class CppLangTranslator(CLikeLangTranslator): res ) else: - if type(_type.parent) is Argument: + if type(type_.parent) is Argument: return 'const {0} &'.format(res) else: return '{0}'.format(res) @@ -1066,14 +1131,7 @@ class CppLangTranslator(CLikeLangTranslator): ) def translate_method_as_prototype(self, method, showStdNs=True, namespace=None): - _class = method.find_first_ancestor_by_type(Class, Interface) - if namespace is not None: - if _class.name.to_c() in self.ambigousTypes: - nsName = None - else: - nsName = namespace.name if namespace is not GlobalNs else None - else: - nsName = _class.name + nsName = self._compute_namespace_name(namespace, method) argsString = '' argStrings = [] @@ -1092,6 +1150,113 @@ class CppLangTranslator(CLikeLangTranslator): def prepend_std(string, prepend): return 'std::' + string if prepend else string + def _compute_namespace_name(self, namespace, obj): + nsName = Translator._compute_namespace_name(self, namespace, obj) + if self._get_object_name(obj).to_c() in self.ambigousTypes: + nsName = None + return nsName + + +class JavaLangTranslator(CLikeLangTranslator): + def __init__(self): + self.nameTranslator = metaname.Translator.get('Java') + self.nilToken = 'null' + self.falseConstantToken = 'false' + self.trueConstantToken = 'true' + + def translate_base_type(self, type_, native=False, jni=False, isReturn=False, namespace=None): + if type_.name == 'string': + if jni: + return 'jstring' + return 'String' + elif type_.name == 'integer': + if type_.size is not None and type_.isref: + if jni: + return 'jbyteArray' + return 'byte[]' + if jni: + return 'jint' + return 'int' + elif type_.name == 'boolean': + if jni: + return 'jboolean' + return 'boolean' + elif type_.name == 'floatant': + if jni: + return 'jfloat' + return 'float' + elif type_.name == 'size': + if jni: + return 'jint' + return 'int' + elif type_.name == 'time': + if jni: + return 'jlong' + return 'long' + elif type_.name == 'status': + if jni: + return 'jint' + if native: + return 'int' + return 'void' + elif type_.name == 'string_array': + if jni: + return 'jobjectArray' + return 'String[]' + elif type_.name == 'character': + if jni: + return 'jchar' + return 'char' + elif type_.name == 'void': + if isReturn: + return 'void' + if jni: + return 'jobject' + return 'Object' + return type_.name + + def translate_enum_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if native: + return 'int' + elif jni: + return 'jint' + else: + nsName = self._compute_namespace_name(namespace, _type) + return _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) + + def translate_class_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if jni: + return 'jobject' + nsName = self._compute_namespace_name(namespace, _type) + return _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) + + def translate_list_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if jni: + if type(_type.containedTypeDesc) is ClassType: + return 'jobjectArray' + elif type(_type.containedTypeDesc) is BaseType: + if _type.containedTypeDesc.name == 'string': + return 'jobjectArray' + return _type.containedTypeDesc.translate(self, jni=True) + 'Array' + elif type(_type.containedTypeDesc) is EnumType: + ptrtype = _type.containedTypeDesc.translate(self, native=native) + ptrtype = '' + if type(_type.containedTypeDesc) is ClassType: + ptrtype = _type.containedTypeDesc.translate(self, native=native) + elif type(_type.containedTypeDesc) is BaseType: + ptrtype = _type.containedTypeDesc.translate(self, native=native) + elif type(_type.containedTypeDesc) is EnumType: + ptrtype = _type.containedTypeDesc.translate(self, native=native) + else: + if _type.containedTypeDesc: + raise Error('translation of bctbx_list_t of ' + _type.containedTypeDesc.name) + else: + raise Error('translation of bctbx_list_t of unknow type !') + return ptrtype + '[]' + + def translate_argument(self, arg, native=False, jni=False): + return '{0} {1}'.format(arg.type.translate(self, native=native, jni=jni), arg.name.translate(self.nameTranslator)) + class CSharpLangTranslator(CLikeLangTranslator): def __init__(self): diff --git a/tools/metaname.py b/tools/metaname.py index 3514f9df0..e1efd8bff 100644 --- a/tools/metaname.py +++ b/tools/metaname.py @@ -103,7 +103,7 @@ class Name(object): res += elem.title() return res else: - return Name.to_camel_case(self.prev, fullName=True, lower=lower) + Name.to_camel_case(self) + return self.prev.to_camel_case(fullName=True, lower=lower) + self.to_camel_case() def concatenate(self, upper=False, fullName=False): if self.prev is None or not fullName: @@ -146,7 +146,10 @@ class Name(object): class ClassName(Name): def to_c(self, addBrackets=False): return self.to_camel_case(fullName=True) - + + def from_c(self, name, **kargs): + self.from_camel_case(name, **kargs) + def translate(self, translator, **params): return translator.translate_class_name(self, **params) @@ -154,7 +157,11 @@ class ClassName(Name): class InterfaceName(ClassName): def to_c(self, addBrackets=False): return ClassName.to_c(self)[:-8] + 'Cbs' - + + def from_c(self, **kargs): + ClassName.from_c(self, **kargs) + self.words[-1] = 'listener' + def translate(self, translator, **params): return translator.translate_interface_name(self, **params) @@ -189,6 +196,9 @@ class MethodName(Name): if addBrackets: cName += '()' return cName + + def from_c(self, **kargs): + self.from_snake_case(**kargs) def translate(self, translator, **params): return translator.translate_method_name(self, **params) @@ -198,6 +208,9 @@ class ArgName(Name): def to_c(self, addBrackets=False): return self.to_snake_case() + def from_c(self, **kargs): + self.from_snake_case(**kargs) + def translate(self, translator, **params): return translator.translate_argument_name(self, **params) @@ -321,9 +334,6 @@ class CppTranslator(JavaTranslator): JavaTranslator.__init__(self) self.nsSep = '::' self.keyWordEscapes = {'new' : '_new'} - - def translate_enumerator_name(self, name, **params): - return self.translate_enum_name(name.prev, **params) + name.to_camel_case() class CSharpTranslator(JavaTranslator): diff --git a/wrappers/cpp/class_header.mustache b/wrappers/cpp/class_header.mustache index 674d93e48..abf06361c 100644 --- a/wrappers/cpp/class_header.mustache +++ b/wrappers/cpp/class_header.mustache @@ -46,7 +46,7 @@ struct {{{privCClassName}}}; namespace linphone { {{#priorDeclarations}} - class {{{name}}}; + {{{declaration}}}; {{/priorDeclarations}} {{#_class}} @@ -69,6 +69,30 @@ namespace linphone { {{/friendClasses}} public: + {{#enums}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + * + */ + {{/doc}} + enum class {{name}} { + {{#enumerators}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + */ + {{/doc}} + {{name}}{{#value}} = {{{value}}}{{/value}}{{#notLast}},{{/notLast}} + {{/enumerators}} + }; + + {{/enums}} + {{#isNotListener}} {{#isrefcountable}} {{{className}}}(void *ptr, bool takeRef=true); diff --git a/wrappers/cpp/enums_header.mustache b/wrappers/cpp/enums_header.mustache index 648a19e77..026f70e38 100644 --- a/wrappers/cpp/enums_header.mustache +++ b/wrappers/cpp/enums_header.mustache @@ -30,7 +30,7 @@ namespace linphone { * */ {{/doc}} - enum {{name}} { + enum class {{name}} { {{#enumerators}} {{#doc}} /** diff --git a/wrappers/cpp/genwrapper.py b/wrappers/cpp/genwrapper.py index bd99465e6..5d34caf13 100755 --- a/wrappers/cpp/genwrapper.py +++ b/wrappers/cpp/genwrapper.py @@ -36,19 +36,16 @@ import metaname class CppTranslator(object): sharedPtrTypeExtractor = re.compile('^(const )?std::shared_ptr<(.+)>( &)?$') - def __init__(self): - self.ambigousTypes = ['LinphonePayloadType'] + def __init__(self, rootNs=None): self.nameTranslator = metaname.Translator.get('Cpp') self.langTranslator = AbsApi.Translator.get('Cpp') self.langTranslator.ambigousTypes.append('LinphonePayloadType') self.docTranslator = metadoc.DoxygenTranslator('Cpp') - - def is_ambigous_type(self, _type): - return _type.name in self.ambigousTypes or (_type.name == 'list' and self.is_ambigous_type(_type.containedTypeDesc)) + self.rootNs = rootNs def translate_enum(self, enum): enumDict = {} - enumDict['name'] = enum.name.to_camel_case() + enumDict['name'] = enum.name.translate(self.nameTranslator) enumDict['doc'] = enum.briefDescription.translate(self.docTranslator) enumDict['enumerators'] = [] for enumerator in enum.enumerators: @@ -87,6 +84,7 @@ class CppTranslator(object): 'cClassName' : '::' + _class.name.to_c(), 'privCClassName' : '_' + _class.name.to_c(), 'parentClassName' : 'Object' if _class.refcountable else None, + 'enums' : [], 'methods' : [], 'staticMethods' : [], 'wrapperCbs' : [], @@ -120,6 +118,9 @@ class CppTranslator(object): classDict['userDataSetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_set_user_data' classDict['userDataGetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_get_user_data' classDict['currentCallbacksGetter'] = _class.name.to_snake_case(fullName=True) + '_get_current_callbacks' + + for enum in _class.enums: + classDict['enums'].append(self.translate_enum(enum)) for _property in _class.properties: classDict['methods'] += self.translate_property(_property) @@ -187,11 +188,11 @@ class CppTranslator(object): return res def translate_method(self, method, genImpl=True): - namespace = method.find_first_ancestor_by_type(AbsApi.Namespace) + namespace = method.find_first_ancestor_by_type(AbsApi.Class, AbsApi.Interface) methodDict = { - 'declPrototype': method.translate_as_prototype(self.langTranslator), - 'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace), + 'declPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace), + 'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=AbsApi.GlobalNs), 'deprecated': method.deprecated, 'suffix': '', } @@ -355,6 +356,7 @@ class ClassHeader(object): else: self._class = translator.translate_interface(_class) + self.rootNs = translator.rootNs self.define = '_{0}_HH'.format(_class.name.to_snake_case(upper=True, fullName=True)) self.filename = '{0}.hh'.format(_class.name.to_snake_case()) self.priorDeclarations = [] @@ -362,16 +364,12 @@ class ClassHeader(object): self.includes = {'internal': [], 'external': []} includes = self.needed_includes(_class) - for include in includes['internal']: - if include == 'enums': - self.includes['internal'].append({'name': include}) - else: - className = metaname.ClassName() - className.from_snake_case(include) - self.priorDeclarations.append({'name': className.to_camel_case()}) for include in includes['external']: self.includes['external'].append({'name': include}) + + for include in includes['internal']: + self.includes['internal'].append({'name': include}) def needed_includes(self, _class): includes = {'internal': [], 'external': []} @@ -394,7 +392,8 @@ class ClassHeader(object): self._needed_includes_from_type(arg.type, includes) if isinstance(_class, AbsApi.Class) and _class.listenerInterface is not None: - self._add_include(includes, 'internal', _class.listenerInterface.name.to_snake_case()) + decl = 'class ' + _class.listenerInterface.name.translate(metaname.Translator.get('Cpp')) + self._add_prior_declaration(decl) currentClassInclude = _class.name.to_snake_case() if currentClassInclude in includes['internal']: @@ -407,26 +406,41 @@ class ClassHeader(object): for arg in method.args: self._needed_includes_from_type(arg.type, includes) - def _needed_includes_from_type(self, _type, includes): - if isinstance(_type, AbsApi.ClassType): - self._add_include(includes, 'external', 'memory') - if _type.desc is not None: - self._add_include(includes, 'internal', _type.desc.name.to_snake_case()) - elif isinstance(_type, AbsApi.EnumType): - self._add_include(includes, 'internal', 'enums') - elif isinstance(_type, AbsApi.BaseType): - if _type.name == 'integer' and isinstance(_type.size, int): + def _needed_includes_from_type(self, type_, includes): + translator = metaname.Translator.get('Cpp') + if isinstance(type_, AbsApi.ClassType): + class_ = type_.desc + if class_.parent == self.rootNs: + decl = 'class ' + class_.name.translate(translator) + self._add_prior_declaration(decl) + else: + rootClass = class_.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True) + self._add_include(includes, 'internal', rootClass.name.to_snake_case()) + elif isinstance(type_, AbsApi.EnumType): + enum = type_.desc + if enum.parent == self.rootNs: + headerFile = 'enums' + else: + rootClass = enum.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True) + headerFile = rootClass.name.to_snake_case() + self._add_include(includes, 'internal', headerFile) + elif isinstance(type_, AbsApi.BaseType): + if type_.name == 'integer' and isinstance(type_.size, int): self._add_include(includes, 'external', 'cstdint') - elif _type.name == 'string': + elif type_.name == 'string': self._add_include(includes, 'external', 'string') - elif isinstance(_type, AbsApi.ListType): + elif isinstance(type_, AbsApi.ListType): self._add_include(includes, 'external', 'list') - self._needed_includes_from_type(_type.containedTypeDesc, includes) + self._needed_includes_from_type(type_.containedTypeDesc, includes) def _add_include(self, includes, location, name): if not name in includes[location]: includes[location].append(name) + def _add_prior_declaration(self, decl): + if next((x for x in self.priorDeclarations if x['declaration']==decl), None) is None: + self.priorDeclarations.append({'declaration': decl}) + class MainHeader(object): def __init__(self): @@ -453,18 +467,16 @@ class GenWrapper(object): self.parser = AbsApi.CParser(project) self.parser.parse_all() - self.translator = CppTranslator() + self.translator = CppTranslator(self.parser.namespace) self.renderer = pystache.Renderer() self.mainHeader = MainHeader() self.impl = ClassImpl() def render_all(self): header = EnumsHeader(self.translator) - for item in self.parser.enumsIndex.items(): - if item[1] is not None: - header.add_enum(item[1]) - else: - logging.info('{0} enum won\'t be translated because of parsing errors'.format(item[0])) + + for enum in self.parser.namespace.enums: + header.add_enum(enum) self.render(header, self.includedir + '/enums.hh') self.mainHeader.add_include('enums.hh') diff --git a/wrappers/java/CMakeLists.txt b/wrappers/java/CMakeLists.txt index c6d29d950..6f6cda660 100644 --- a/wrappers/java/CMakeLists.txt +++ b/wrappers/java/CMakeLists.txt @@ -21,6 +21,7 @@ ############################################################################ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc" + COMMAND ${CMAKE_COMMAND} -E remove -f java/org/linphone/core/* src/* COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml" "-o" "${CMAKE_CURRENT_BINARY_DIR}" DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py ${LINPHONE_HEADER_FILES} ${PROJECT_SOURCE_DIR}/tools/metadoc.py diff --git a/wrappers/java/genwrapper.py b/wrappers/java/genwrapper.py index b5b68a12f..d93043d52 100755 --- a/wrappers/java/genwrapper.py +++ b/wrappers/java/genwrapper.py @@ -28,55 +28,8 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) import genapixml as CApi import abstractapi as AbsApi import metadoc +import metaname -########################################################################## - -ENUMS_LIST = { - 'AccountCreatorActivationCodeStatus': 'AccountCreator', - 'AccountCreatorDomainStatus': 'AccountCreator', - 'AccountCreatorEmailStatus': 'AccountCreator', - 'AccountCreatorLanguageStatus': 'AccountCreator', - 'AccountCreatorPasswordStatus': 'AccountCreator', - 'AccountCreatorPhoneNumberStatus': 'AccountCreator', - 'AccountCreatorStatus': 'AccountCreator', - 'AccountCreatorTransportStatus': 'AccountCreator', - 'AccountCreatorUsernameStatus': 'AccountCreator', - 'AddressFamily': 'CallStats', - 'AudioRoute': 'Call', - 'AuthMethod': 'Core', - 'CallDir': 'Call', - 'CallState': 'Call', - 'CallStatus': 'CallLog', - 'ChatRoomState': 'ChatRoom', - 'ChatMessageDirection': 'ChatMessage', - 'ChatMessageState': 'ChatMessage', - 'ConfiguringState': 'Core', - 'ConsolidatedPresence': 'PresenceModel', - 'CoreLogCollectionUploadState': 'Core', - 'EcCalibratorStatus': 'Core', - 'EventLogType': 'EventLog', - 'GlobalState': 'Core', - 'FriendListStatus': 'FriendList', - 'FriendListSyncStatus': 'FriendList', - 'IceState': 'CallStats', - 'LimeState': 'Core', - 'LogCollectionState': 'Core', - 'MediaDirection': 'Core', - 'MediaEncryption': 'Core', - 'PlayerState': 'Player', - 'PresenceActivityType': 'PresenceActivity', - 'PublishState': 'Event', - 'RegistrationState': 'Core', - 'StreamType': 'CallStats', - 'SubscriptionDir': 'Event', - 'SubscribePolicy': 'Friend', - 'TransportType': 'Address', - 'TunnelMode': 'Tunnel', - 'UpnpState': 'Core', - 'VersionUpdateCheckResult': 'Core', - 'XmlRpcRequestArgType': 'XmlRpcRequest', - 'XmlRpcRequestStatus': 'XmlRpcRequest', -} CORE_ACCESSOR_LIST = [ 'Call', @@ -89,7 +42,89 @@ CORE_ACCESSOR_LIST = [ 'ProxyConfig' ] -########################################################################## + +class JNINameTranslator(metaname.Translator): + _instance = None + + @staticmethod + def get(): + if JNINameTranslator._instance is None: + JNINameTranslator._instance = JNINameTranslator() + return JNINameTranslator._instance + + def translate_class_name(self, name, **params): + translated_name = name.to_camel_case() + if name.prev is not None: + return name.prev.translate(self) + self._getseparator(name.prev) + translated_name + else: + return translated_name + + def translate_interface_name(self, name, **params): + return self.translate_class_name(name, **params) + + def translate_enum_name(self, name, **params): + return self.translate_class_name(name, **params) + + def translate_enumerator_name(self, name, **params): + raise NotImplemented() + + def translate_method_name(self, name, **params): + raise NotImplemented() + + def translate_namespace_name(self, name, **params): + translated_name = name.to_snake_case() + if name.prev is not None: + return name.prev.translate(self) + self._getseparator(name.prev) + translated_name + else: + return translated_name + + def translate_argument_name(self, name, **params): + raise NotImplemented() + + def translate_property_name(self, name, **params): + raise NotImplemented() + + def _getseparator(self, previous_name): + if isinstance(previous_name, metaname.NamespaceName): + return '/' + elif isinstance(previous_name, metaname.ClassName): + return '$' + else: + raise TypeError("no separator for '{0}' type".format(type(previous_name))) + + +class JNILangTranslator(AbsApi.Translator): + _instance = None + + @staticmethod + def get(): + if JNILangTranslator._instance is None: + JNILangTranslator._instance = JNILangTranslator() + return JNILangTranslator._instance + + def translate_base_type(self, type_): + if type_.name == 'string': + return 'Ljava/lang/String;' + elif type_.name == 'integer': + return 'I' + elif type_.name == 'boolean': + return 'Z' + elif type_.name == 'floatant': + return 'F' + elif type_.name == 'size': + return 'I' + elif type_.name == 'time': + return 'I' + elif type_.name == 'status': + return 'I' + elif type_.name == 'string_array': + return '[Ljava/lang/String;' + elif type_.name == 'character': + return 'C' + elif type_.name == 'void': + return 'V' + return type_.name + class JavaTranslator(object): def __init__(self, packageName, exceptions): @@ -101,8 +136,15 @@ class JavaTranslator(object): self.jni_package += directory + '_' self.jni_path += directory + '/' + self.nameTranslator = metaname.Translator.get('Java') + self.langTranslator = AbsApi.Translator.get('Java') self.docTranslator = metadoc.JavaDocTranslator() + self.jninameTranslator = JNINameTranslator.get() + self.jnilangTranslator = JNILangTranslator.get() + + self.clangTranslator = AbsApi.Translator.get('C') + def throws_exception(self, _type): if not self.exceptions: return False @@ -111,177 +153,6 @@ class JavaTranslator(object): return True return False - def translate_argument_name(self, _argName): - return _argName.to_snake_case() - - def translate_java_jni_enum_name(self, _enum): - name = _enum.name.to_camel_case() - if name in ENUMS_LIST: - className = ENUMS_LIST[name] - if name.startswith(className): - name = name[len(className):] - name = className + '$' + name - return name - - def translate_java_jni_base_type_name(self, _type): - if _type == 'string': - return 'Ljava/lang/String;' - elif _type == 'integer': - return 'I' - elif _type == 'boolean': - return 'Z' - elif _type == 'floatant': - return 'F' - elif _type == 'size': - return 'I' - elif _type == 'time': - return 'I' - elif _type == 'status': - return 'I' - elif _type == 'string_array': - return '[Ljava/lang/String;' - elif _type == 'character': - return 'C' - elif _type == 'void': - return 'V' - return _type - - def translate_as_c_base_type(self, t): - _type = t.name - if _type == 'string': - return 'char *' - elif _type == 'integer': - if t.size is None: - if t.isUnsigned: - return 'unsigned int' - return 'int' - inttype = 'int{0}_t'.format(t.size) - if t.isUnsigned: - inttype = 'u' + inttype - if t.isref: - inttype = inttype + ' *' - if t.isconst: - inttype = 'const ' + inttype - return inttype - elif _type == 'boolean': - return 'bool_t' - elif _type == 'floatant': - return 'float' - elif _type == 'size': - return 'size_t' - elif _type == 'time': - return 'time_t' - elif _type == 'status': - return 'int' - elif _type == 'string_array': - return 'char **' - elif _type == 'character': - return 'char' - elif _type == 'void': - if t.isref: - return 'void *' - return 'void' - return _type - - def translate_type(self, _type, native=False, jni=False, isReturn=False): - if type(_type) is AbsApi.ListType: - if jni: - if type(_type.containedTypeDesc) is AbsApi.ClassType: - return 'jobjectArray' - elif type(_type.containedTypeDesc) is AbsApi.BaseType: - if _type.containedTypeDesc.name == 'string': - return 'jobjectArray' - return self.translate_type(_type.containedTypeDesc, jni=True) + 'Array' - elif type(_type.containedTypeDesc) is AbsApi.EnumType: - ptrtype = self.translate_type(_type.containedTypeDesc, native) - ptrtype = '' - if type(_type.containedTypeDesc) is AbsApi.ClassType: - ptrtype = self.translate_type(_type.containedTypeDesc, native) - elif type(_type.containedTypeDesc) is AbsApi.BaseType: - ptrtype = self.translate_type(_type.containedTypeDesc, native) - elif type(_type.containedTypeDesc) is AbsApi.EnumType: - ptrtype = self.translate_type(_type.containedTypeDesc, native) - else: - if _type.containedTypeDesc: - raise AbsApi.Error('translation of bctbx_list_t of ' + _type.containedTypeDesc.name) - else: - raise AbsApi.Error('translation of bctbx_list_t of unknow type !') - return ptrtype + '[]' - - elif type(_type) is AbsApi.ClassType: - if jni: - return 'jobject' - return _type.desc.name.to_camel_case() - elif type(_type) is AbsApi.EnumType: - if native: - return 'int' - elif jni: - return 'jint' - if _type.desc.name.to_camel_case() == "XmlRpcStatus": - return "XmlRpcRequest.Status" - elif _type.desc.name.to_camel_case() == "XmlRpcArgType": - return "XmlRpcRequest.ArgType" - name = _type.desc.name.to_camel_case() - if name in ENUMS_LIST: - className = ENUMS_LIST[name] - if name.startswith(className): - name = name[len(className):] - name = className + '.' + name - return name - elif type(_type) is AbsApi.BaseType: - if _type.name == 'string': - if jni: - return 'jstring' - return 'String' - elif _type.name == 'integer': - if _type.size is not None and _type.isref: - if jni: - return 'jbyteArray' - return 'byte[]' - if jni: - return 'jint' - return 'int' - elif _type.name == 'boolean': - if jni: - return 'jboolean' - return 'boolean' - elif _type.name == 'floatant': - if jni: - return 'jfloat' - return 'float' - elif _type.name == 'size': - if jni: - return 'jint' - return 'int' - elif _type.name == 'time': - if jni: - return 'jlong' - return 'long' - elif _type.name == 'status': - if jni: - return 'jint' - if native: - return 'int' - return 'void' - elif _type.name == 'string_array': - if jni: - return 'jobjectArray' - return 'String[]' - elif _type.name == 'character': - if jni: - return 'jchar' - return 'char' - elif _type.name == 'void': - if isReturn: - return 'void' - if jni: - return 'jobject' - return 'Object' - return _type.name - - def translate_argument(self, _arg, native=False, jni=False): - return '{0} {1}'.format(self.translate_type(_arg.type, native, jni), self.translate_argument_name(_arg.name)) - def translate_property(self, _property, _hasCoreAccessor): properties = [] if _property.getter is not None: @@ -331,8 +202,8 @@ class JavaTranslator(object): def translate_method(self, _method, _hasCoreAccessor=False): methodDict = {} - methodDict['return'] = self.translate_type(_method.returnType, isReturn=True) - methodDict['return_native'] = self.translate_type(_method.returnType, native=True, isReturn=True) + methodDict['return'] = _method.returnType.translate(self.langTranslator, isReturn=True) + methodDict['return_native'] = _method.returnType.translate(self.langTranslator, native=True, isReturn=True) methodDict['return_keyword'] = '' if methodDict['return'] == 'void' else 'return ' methodDict['hasReturn'] = not methodDict['return'] == 'void' @@ -357,13 +228,13 @@ class JavaTranslator(object): methodDict['native_params'] += ', ' methodDict['native_params_impl'] += ', ' - methodDict['params'] += self.translate_argument(arg) - methodDict['native_params'] += self.translate_argument(arg, True) - methodDict['static_native_params'] += self.translate_argument(arg, True) + methodDict['params'] += arg.translate(self.langTranslator) + methodDict['native_params'] += arg.translate(self.langTranslator, native=True) + methodDict['static_native_params'] += arg.translate(self.langTranslator, native=True) if type(arg.type) is AbsApi.EnumType: - methodDict['native_params_impl'] += self.translate_argument_name(arg.name) + '.toInt()' + methodDict['native_params_impl'] += arg.name.translate(self.nameTranslator) + '.toInt()' else: - methodDict['native_params_impl'] += self.translate_argument_name(arg.name) + methodDict['native_params_impl'] += arg.name.translate(self.nameTranslator) methodDict['deprecated'] = _method.deprecated methodDict['doc'] = _method.briefDescription.translate(self.docTranslator) if _method.briefDescription is not None else None @@ -371,8 +242,8 @@ class JavaTranslator(object): return methodDict def translate_jni_method(self, className, _method, static=False): - jni_blacklist = ['linphone_call_set_native_video_window_id',\ - 'linphone_core_set_native_preview_window_id',\ + jni_blacklist = ['linphone_call_set_native_video_window_id', + 'linphone_core_set_native_preview_window_id', 'linphone_core_set_native_video_window_id'] methodDict = {'notEmpty': True} @@ -382,7 +253,7 @@ class JavaTranslator(object): methodDict['isLinphoneFactory'] = className.to_camel_case() == 'Factory' methodDict['jniPath'] = self.jni_path - methodDict['return'] = self.translate_type(_method.returnType, jni=True, isReturn=True) + methodDict['return'] = _method.returnType.translate(self.langTranslator, jni=True, isReturn=True) methodDict['hasListReturn'] = methodDict['return'] == 'jobjectArray' methodDict['hasByteArrayReturn'] = methodDict['return'] == 'jbyteArray' methodDict['hasReturn'] = not methodDict['return'] == 'void' and not methodDict['hasListReturn'] and not methodDict['hasByteArrayReturn'] @@ -396,11 +267,11 @@ class JavaTranslator(object): elif _method.name.to_snake_case() == 'create_core_with_config': methodDict['c_name'] = 'linphone_' + className.to_snake_case() + "_" + 'create_core_with_config_3' methodDict['returnObject'] = methodDict['hasReturn'] and type(_method.returnType) is AbsApi.ClassType - methodDict['returnClassName'] = self.translate_type(_method.returnType) + methodDict['returnClassName'] = _method.returnType.translate(self.langTranslator) methodDict['isRealObjectArray'] = False methodDict['isStringObjectArray'] = False - methodDict['c_type_return'] = self.translate_as_c_base_type(_method.returnType) - + methodDict['c_type_return'] = _method.returnType.translate(self.clangTranslator) + if methodDict['c_name'] in jni_blacklist: return {'notEmpty': False} @@ -432,8 +303,8 @@ class JavaTranslator(object): else: methodDict['params_impl'] += ', ' - methodDict['params'] += self.translate_argument(arg, jni=True) - argname = self.translate_argument_name(arg.name) + methodDict['params'] += arg.translate(self.langTranslator, jni=True) + argname = arg.name.translate(self.nameTranslator) if type(arg.type) is AbsApi.ClassType: classCName = 'Linphone' + arg.type.desc.name.to_camel_case() @@ -441,7 +312,7 @@ class JavaTranslator(object): classCName = 'Linphone' + arg.type.desc.name.to_camel_case()[:-8] + 'Cbs' methodDict['objects'].append({'object': argname, 'objectClassCName': classCName}) methodDict['params_impl'] += 'c_' + argname - + elif type(arg.type) is AbsApi.ListType: isStringList = type(arg.type.containedTypeDesc) is AbsApi.BaseType and arg.type.containedTypeDesc.name == 'string' isObjList = type(arg.type.containedTypeDesc) is AbsApi.ClassType @@ -451,16 +322,16 @@ class JavaTranslator(object): elif type(arg.type) is AbsApi.EnumType: argCType = arg.type.name methodDict['params_impl'] += '(' + argCType + ') ' + argname - + elif type(arg.type) is AbsApi.BaseType: if arg.type.name == 'integer' and arg.type.size is not None and arg.type.isref: - methodDict['bytes'].append({'bytesargname': argname, 'bytesargtype' : self.translate_as_c_base_type(arg.type)}) + methodDict['bytes'].append({'bytesargname': argname, 'bytesargtype' : arg.type.translate(self.clangTranslator)}) methodDict['params_impl'] += 'c_' + argname elif arg.type.name == 'string': methodDict['strings'].append({'string': argname}) methodDict['params_impl'] += 'c_' + argname else: - methodDict['params_impl'] += '(' + self.translate_as_c_base_type(arg.type) + ')' + argname + methodDict['params_impl'] += '(' + arg.type.translate(self.clangTranslator) + ')' + argname else: methodDict['params_impl'] += argname @@ -517,27 +388,25 @@ class JavaTranslator(object): def translate_jni_interface(self, _class, className, _method): methodDict = {} - listenerName = 'Linphone' + className.to_camel_case() - methodDict['classCName'] = listenerName[:-8] #Remove Listener at the end - methodDict['className'] = className.to_camel_case() - methodDict['classImplName'] = className.to_camel_case() + 'Impl' + methodDict['classCName'] = className.to_c() + methodDict['className'] = className.translate(self.nameTranslator) + methodDict['classImplName'] = methodDict['className'] + 'Impl' methodDict['jniPath'] = self.jni_path - methodDict['cPrefix'] = 'linphone_' + className.to_snake_case()[:-9] # Remove _listener at the end - methodDict['callbackName'] = methodDict['cPrefix'] + '_' + _method.name.to_snake_case() - methodDict['jname'] = _method.name.to_camel_case(lower=True) - methodDict['return'] = self.translate_as_c_base_type(_method.returnType) + methodDict['cPrefix'] = _class.name.to_snake_case(fullName=True) + methodDict['callbackName'] = '_{0}_cb'.format(_method.name.to_snake_case(fullName=True)) + methodDict['jname'] = _method.name.translate(self.nameTranslator) + methodDict['return'] = _method.returnType.translate(self.clangTranslator) methodDict['jniUpcallMethod'] = 'CallVoidMethod' methodDict['isJniUpcallBasicType'] = False methodDict['isJniUpcallObject'] = False if type(_method.returnType) is AbsApi.ClassType: - methodDict['return'] += '*' methodDict['jniUpcallMethod'] = 'CallObjectMethod' methodDict['isJniUpcallObject'] = True methodDict['jniUpcallType'] = 'jobject' elif type(_method.returnType) is AbsApi.BaseType: if not _method.returnType.name == 'void': methodDict['jniUpcallMethod'] = 'CallIntMethod' - methodDict['jniUpcallType'] = self.translate_type(_method.returnType, jni=True) + methodDict['jniUpcallType'] = _method.returnType.translate(self.langTranslator, jni=True) methodDict['isJniUpcallBasicType'] = True methodDict['returnIfFail'] = '' if methodDict['return'] == 'void' else ' NULL' methodDict['hasReturn'] = not methodDict['return'] == 'void' @@ -552,40 +421,33 @@ class JavaTranslator(object): methodDict['jparams'] = '(' methodDict['params_impl'] = '' for arg in _method.args: - argname = self.translate_argument_name(arg.name) + argname = arg.name.translate(self.nameTranslator) if arg is not _method.args[0]: methodDict['params'] += ', ' methodDict['params_impl'] += ', ' else: - methodDict['firstParam'] = argname + methodDict['firstParam'] = argname - if (arg.type.isconst): - methodDict['params'] += 'const ' + methodDict['params'] += '{0} {1}'.format(arg.type.translate(self.clangTranslator), argname) if type(arg.type) is AbsApi.ClassType: - methodDict['params'] += 'Linphone' + arg.type.desc.name.to_camel_case() + ' *' + argname methodDict['jparams'] += 'L' + self.jni_path + arg.type.desc.name.to_camel_case() + ';' methodDict['params_impl'] += 'j_' + argname methodDict['jobjects'].append({'objectName': argname, 'className': arg.type.desc.name.to_camel_case(), }) elif type(arg.type) is AbsApi.BaseType: - methodDict['params'] += self.translate_as_c_base_type(arg.type) + ' ' + argname - methodDict['jparams'] += self.translate_java_jni_base_type_name(arg.type.name) + methodDict['jparams'] += arg.type.translate(self.jnilangTranslator) if arg.type.name == 'string': methodDict['params_impl'] += 'j_' + argname methodDict['jstrings'].append({'stringName': argname,}) else: methodDict['params_impl'] += argname elif type(arg.type) is AbsApi.EnumType: - methodDict['params'] += 'Linphone' + arg.type.desc.name.to_camel_case() + ' ' + argname - methodDict['jparams'] += 'L' + self.jni_path + self.translate_java_jni_enum_name(arg.type.desc) + ';' + methodDict['jparams'] += 'L' + self.jni_path + arg.type.desc.name.translate(self.jninameTranslator) + ';' methodDict['params_impl'] += 'j_' + argname - methodDict['jenums'].append({'enumName': argname, 'cEnumPrefix': 'linphone_' + arg.type.desc.name.to_snake_case()}) + methodDict['jenums'].append({'enumName': argname, 'cEnumPrefix': arg.type.desc.name.to_snake_case(fullName=True)}) elif type(arg.type) is AbsApi.ListType: - #TODO #FIXME handle bctbx_list_t as callback param - methodDict['params'] += 'const bctbx_list_t *' + argname methodDict['jparams'] += '[L' + self.jni_path + arg.type.containedTypeDesc.name + ';' methodDict['params_impl'] += 'NULL' - #methodDict['jobjects'].append({'objectName': argname, 'className': arg.type.containedTypeDesc.name, }) methodDict['jparams'] += ')' if (methodDict['return'] == 'void'): @@ -652,22 +514,15 @@ class JavaTranslator(object): class JavaEnum(object): def __init__(self, package, _enum, translator): + javaNameTranslator = metaname.Translator.get('Java') self._class = translator.translate_enum(_enum) self.packageName = package - self.className = _enum.name.to_camel_case() - if self.className == 'XmlRpcArgType': - self.className = 'XmlRpcRequestArgType' - elif self.className == 'XmlRpcStatus': - self.className = 'XmlRpcRequestStatus' - self.cPrefix = 'linphone_' + _enum.name.to_snake_case() + self.className = _enum.name.translate(javaNameTranslator) + self.cPrefix = _enum.name.to_snake_case(fullName=True) self.filename = self.className + ".java" self.values = self._class['values'] self.doc = self._class['doc'] - self.jniName = translator.translate_java_jni_enum_name(_enum) - if self.className == 'XmlRpcRequestArgType': - self.jniName = 'XmlRpcRequest$ArgType' - elif self.className == 'XmlRpcRequestStatus': - self.jniName = 'XmlRpcRequest$Status' + self.jniName = _enum.name.translate(JNINameTranslator.get()) class JniInterface(object): def __init__(self, javaClass, apiClass): @@ -679,10 +534,8 @@ class JniInterface(object): self.callbacks = [] listener = apiClass.listenerInterface for method in listener.methods: - cb = 'linphone_' + listener.name.to_snake_case()[:-9] # Remove _listener at the end - cbName = cb + '_' + method.name.to_snake_case() self.callbacks.append({ - 'callbackName': cbName, + 'callbackName': '_{0}_cb'.format(method.name.to_snake_case(fullName=True)), 'callback': method.name.to_snake_case()[3:], # Remove the on_ }) @@ -712,9 +565,9 @@ class JavaClass(object): self.isLinphoneFactory = self._class['isLinphoneFactory'] self.isLinphoneCore = self._class['isLinphoneCore'] self.isNotLinphoneFactory = not self.isLinphoneFactory + self.cName = _class.name.to_c() self.hasCoreAccessor = self._class['hasCoreAccessor'] - self.cName = 'Linphone' + _class.name.to_camel_case() - self.cPrefix = 'linphone_' + _class.name.to_snake_case() + self.cPrefix = _class.name.to_snake_case(fullName=True) self.packageName = package self.className = _class.name.to_camel_case() self.classImplName = self.className + "Impl" @@ -726,6 +579,8 @@ class JavaClass(object): self.jniMethods = self._class['jniMethods'] self.doc = self._class['doc'] self.enums = [] + for enum in _class.enums: + self.enums.append(JavaEnum(package, enum, translator)) self.jniInterface = None if _class.listenerInterface is not None: self.jniInterface = JniInterface(self, _class) @@ -827,18 +682,19 @@ class GenWrapper(object): project.check() self.parser = AbsApi.CParser(project) - self.parser.functionBl = \ - ['linphone_factory_create_core_with_config',\ - 'linphone_factory_create_core',\ - 'linphone_factory_create_core_2',\ - 'linphone_factory_create_core_with_config_2',\ - 'linphone_vcard_get_belcard',\ - 'linphone_core_get_current_vtable',\ - 'linphone_factory_get',\ - 'linphone_factory_clean',\ - 'linphone_call_zoom_video',\ - 'linphone_core_get_zrtp_cache_db',\ - 'linphone_config_get_range'] + self.parser.functionBl = [ + 'linphone_factory_create_core_with_config', + 'linphone_factory_create_core', + 'linphone_factory_create_core_2', + 'linphone_factory_create_core_with_config_2', + 'linphone_vcard_get_belcard', + 'linphone_core_get_current_vtable', + 'linphone_factory_get', + 'linphone_factory_clean', + 'linphone_call_zoom_video', + 'linphone_core_get_zrtp_cache_db', + 'linphone_config_get_range' + ] self.parser.parse_all() self.translator = JavaTranslator(package, exceptions) self.renderer = pystache.Renderer() @@ -848,27 +704,14 @@ class GenWrapper(object): self.enums = {} self.interfaces = {} self.classes = {} - self.enums_to_remove = [] def render_all(self): - for _interface in self.parser.interfacesIndex.values(): + for _interface in self.parser.namespace.interfaces: self.render_java_interface(_interface) - for _class in self.parser.classesIndex.values(): + for _class in self.parser.namespace.classes: self.render_java_class(_class) - for _enum in self.parser.enumsIndex.items(): - if _enum[1] is not None: - self.render_java_enum(_enum[1]) - - for name, value in self.enums.items(): - self.jni.add_enum(value) - if name in ENUMS_LIST: - className = ENUMS_LIST[name] - logging.info('Enum ' + name + ' belongs to class ' + className) - self.classes[className].add_enum(value) - self.enums_to_remove.append(name) - - for enum in self.enums_to_remove: - self.enums.pop(enum, None) + for enum in self.parser.namespace.enums: + self.render_java_enum(enum) for name, value in self.enums.items(): self.render(value, self.javadir + '/' + value.filename) @@ -898,6 +741,7 @@ class GenWrapper(object): try: javaenum = JavaEnum(self.package, _class, self.translator) self.enums[javaenum.className] = javaenum + self.jni.add_enum(javaenum) except AbsApi.Error as e: logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) @@ -917,6 +761,8 @@ class GenWrapper(object): try: javaclass = JavaClass(self.package, _class, self.translator) self.classes[javaclass.className] = javaclass + for enum in javaclass.enums: + self.jni.add_enum(enum) except AbsApi.Error as e: logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) self.jni.add_methods(javaclass.className, javaclass.jniMethods) diff --git a/wrappers/java/java_class.mustache b/wrappers/java/java_class.mustache index f409b8d84..b827684ee 100644 --- a/wrappers/java/java_class.mustache +++ b/wrappers/java/java_class.mustache @@ -45,7 +45,7 @@ import org.linphone.core.tools.OpenH264DownloadHelper; {{/doc}} public {{#isLinphoneFactory}}abstract class{{/isLinphoneFactory}}{{#isNotLinphoneFactory}}interface{{/isNotLinphoneFactory}} {{className}} { {{#enums}} - enum {{className}} { + enum {{{className}}} { {{#values}} {{#doc}} /** @@ -59,17 +59,17 @@ public {{#isLinphoneFactory}}abstract class{{/isLinphoneFactory}}{{#isNotLinphon {{/values}} protected final int mValue; - private {{className}} (int value) { + private {{{className}}} (int value) { mValue = value; } - static public {{className}} fromInt(int value) throws RuntimeException { + static public {{{className}}} fromInt(int value) throws RuntimeException { switch(value) { {{#values}} case {{value}}: return {{name}}; {{/values}} default: - throw new RuntimeException("Unhandled enum value " + value + " for {{className}}"); + throw new RuntimeException("Unhandled enum value " + value + " for {{{className}}}"); } } diff --git a/wrappers/java/java_enum.mustache b/wrappers/java/java_enum.mustache index 460d47aaf..7f9104f9b 100644 --- a/wrappers/java/java_enum.mustache +++ b/wrappers/java/java_enum.mustache @@ -30,7 +30,7 @@ import {{import}} {{/lines}} */ {{/doc}} -public enum {{className}} { +public enum {{{className}}} { {{#values}} {{#doc}} /** @@ -61,4 +61,4 @@ public enum {{className}} { public int toInt() { return mValue; } -} \ No newline at end of file +} diff --git a/wrappers/java/jni.mustache b/wrappers/java/jni.mustache index 1228d1737..52152d754 100644 --- a/wrappers/java/jni.mustache +++ b/wrappers/java/jni.mustache @@ -291,10 +291,10 @@ static {{return}} {{callbackName}}({{params}}) { } {{#isSingleListener}} - {{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks({{firstParam}}); + {{classCName}} *cbs = {{cPrefix}}_get_callbacks({{firstParam}}); {{/isSingleListener}} {{#isMultiListener}} - {{classCName}}Cbs *cbs = {{cPrefix}}_get_current_callbacks({{firstParam}}); + {{classCName}} *cbs = {{cPrefix}}_get_current_callbacks({{firstParam}}); {{/isMultiListener}} jobject jlistener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs); diff --git a/wrappers/java/migration.sh b/wrappers/java/migration.sh index aad4eca2c..86dd25bc2 100644 --- a/wrappers/java/migration.sh +++ b/wrappers/java/migration.sh @@ -1,5 +1,6 @@ #!/bin/sh +# 1st pass find ./src/android/org/linphone/ -type f -exec sed -i -e "s/import org.linphone.tools/import org.linphone.core.tools/g; \ s/import org.linphone.core.OpenH264DownloadHelperListener/import org.linphone.core.tools.OpenH264DownloadHelperListener/g; \ s/import org.linphone.core.LinphoneCore.Transports/import org.linphone.core.Transports/g; \ @@ -270,7 +271,26 @@ s/linkPhoneNumberWithAccount()/linkAccount()/g; \ s/zoomVideo(/zoom(/g; \ s/mLc.setCpuCount(/\/\/mLc.setCpuCount(/g; \ s/new XmlRpcRequestImpl(/xmlRpcSession.createRequest(/g; \ -s/new XmlRpcSessionImpl(LinphoneManager.getLcIfManagerNotDestroyedOrNull(), /LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(/g" {} \; +s/new XmlRpcSessionImpl(LinphoneManager.getLcIfManagerNotDestroyedOrNull(), /LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(/g;" {} \; + +# 2nd pass +find ./src/android/org/linphone/ -type f -exec sed -i -e "s/Address\.TransportType/TransportType/g; \ +s/\(CallLog\.\)\?CallStatus\([^[:alnum:]_]\)/Call.Status\2/g; \ +s/CallStats\.AddressFamily/AddressFamily/g; \ +s/CallStats\.StreamType/StreamType/g; \ +s/Core\.AuthMethod/AuthMethod/g; \ +s/Core\.ConfiguringState/ConfiguringState/g; \ +s/Core\.EcCalibratorStatus/EcCalibratorStatus/g; \ +s/Core\.GlobalState/GlobalState/g; \ +s/Core\.LimeState/LimeState/g; \ +s/Core\.LogCollectionState/LogCollectionState/g; \ +s/Core\.MediaEncryption/MediaEncryption/g; \ +s/Core\.RegistrationState/RegistrationState/g; \ +s/Core\.VersionUpdateCheckResult/VersionUpdateCheckResult/g; \ +s/Event\.PublishState/PublishState/g; \ +s/Friend\.SubscribePolicy/SubscribePolicy/g; \ +s/XmlRpcRequest\.ArgType/XmlRpcArgType/g; \ +s/XmlRpcRequest\.Status/XmlRpcStatus/g;" {} \; # TODO #Tunnel, TunnelConfig