summaryrefslogtreecommitdiff
path: root/tools/InterfaceGenerator/generator
diff options
context:
space:
mode:
Diffstat (limited to 'tools/InterfaceGenerator/generator')
-rwxr-xr-xtools/InterfaceGenerator/generator/Model.py326
-rwxr-xr-xtools/InterfaceGenerator/generator/__init__.py2
-rwxr-xr-xtools/InterfaceGenerator/generator/generators/SmartFactoryBase.py1684
-rwxr-xr-xtools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py165
-rwxr-xr-xtools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py92
-rwxr-xr-xtools/InterfaceGenerator/generator/generators/__init__.py3
-rwxr-xr-xtools/InterfaceGenerator/generator/parsers/JSONRPC.py89
-rwxr-xr-xtools/InterfaceGenerator/generator/parsers/RPCBase.py758
-rwxr-xr-xtools/InterfaceGenerator/generator/parsers/SDLRPCV1.py14
-rwxr-xr-xtools/InterfaceGenerator/generator/parsers/SDLRPCV2.py88
-rwxr-xr-xtools/InterfaceGenerator/generator/parsers/__init__.py3
11 files changed, 3224 insertions, 0 deletions
diff --git a/tools/InterfaceGenerator/generator/Model.py b/tools/InterfaceGenerator/generator/Model.py
new file mode 100755
index 0000000000..ee458d934a
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/Model.py
@@ -0,0 +1,326 @@
+"""Interface model.
+
+Interface model is represented by Interface class.
+Parser must provide an instance of this model as a result of parsing
+interface definition file.
+Generator must take an instance of this model as input for generating
+output files.
+"""
+
+# In this module there are classes that are used as data container
+# pylint: disable=R0903
+
+import collections
+
+
+class Boolean(object):
+
+ """Boolean type.
+
+ default_value -- default value
+
+ """
+
+ def __init__(self, default_value=None):
+ self.default_value = default_value
+
+
+class Integer(object):
+
+ """Integer type.
+
+ Instance variables:
+ min_value -- minimum allowed value
+ max_value -- maximum allowed value
+ default_value -- default value
+
+ """
+
+ def __init__(self, min_value=None, max_value=None, default_value=None):
+ self.min_value = min_value
+ self.max_value = max_value
+ self.default_value = default_value
+
+
+class Double(object):
+
+ """Floating-point type.
+
+ Instance variables:
+ min_value -- minimum allowed value
+ max_value -- maximum allowed value
+ default_value -- default value
+
+ """
+
+ def __init__(self, min_value=None, max_value=None, default_value=None):
+ self.min_value = min_value
+ self.max_value = max_value
+ self.default_value = default_value
+
+class String(object):
+
+ """String type.
+
+ Instance variables:
+ min_length -- minimum string length
+ max_length -- maximum string length
+ default_value -- default value
+
+ """
+
+ def __init__(self, min_length=None, max_length=None, default_value=None):
+ self.min_length = min_length
+ self.max_length = max_length
+ self.default_value = default_value
+
+
+class Array(object):
+
+ """Array type.
+
+ Instance variables:
+ min_size -- minimum array size
+ max_size -- maximum array size
+ element_type -- type of array element
+
+ """
+
+ def __init__(self, min_size=None, max_size=None, element_type=None):
+ self.min_size = min_size
+ self.max_size = max_size
+ self.element_type = element_type
+
+
+class Issue(object):
+
+ """Issue.
+
+ Instance variables:
+ creator -- issue creator
+ value -- issue text
+
+ """
+
+ def __init__(self, creator=None, value=None):
+ self.creator = creator
+ self.value = value
+
+
+class InterfaceItemBase(object):
+
+ """Base class for interface item.
+
+ Instance variables:
+ name -- item name
+ description -- list of string description elements
+ design_description -- list of string design description elements
+ issues -- list of issues
+ todos -- list of string todo elements
+ platform -- optional platform (string or None)
+ default_value -- default value
+ scope -- optional scope: internal, partner or none (none by defaul, means public)
+
+ """
+
+ def __init__(self, name, description=None, design_description=None,
+ issues=None, todos=None, platform=None, default_value=None, scope=None):
+ self.name = name
+ self.description = description if description is not None else []
+ self.design_description = \
+ design_description if design_description is not None else []
+ self.issues = issues if issues is not None else []
+ self.todos = todos if todos is not None else []
+ self.platform = platform
+ self.default_value = default_value
+ self.scope = scope
+
+
+class EnumElement(InterfaceItemBase):
+
+ """Element of enumeration.
+
+ Instance variables:
+ internal_name -- internal name of an element must be used by a
+ generator if it is provided (not None)
+ value -- optional element value
+
+ """
+
+ def __init__(self, name, description=None, design_description=None,
+ issues=None, todos=None, platform=None, internal_name=None,
+ value=None):
+ super(EnumElement, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform)
+ self.internal_name = internal_name
+ self.value = value
+
+ @property
+ def primary_name(self):
+ """Primary name of the EnumElement.
+
+ Return the 'internal_name' property if presented or 'name' property
+ otherwise.
+
+ """
+ return self.name if self.internal_name is None else self.internal_name
+
+
+class Enum(InterfaceItemBase):
+
+ """Enumeration.
+
+ Instance variables:
+ internal_scope -- optional internal scope
+ elements -- enumeration elements
+
+ """
+
+ def __init__(self, name, description=None, design_description=None,
+ issues=None, todos=None, platform=None, internal_scope=None,
+ elements=None, scope=None):
+ super(Enum, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform, scope=scope)
+
+ self.internal_scope = internal_scope
+ self.elements = \
+ elements if elements is not None else collections.OrderedDict()
+
+
+class EnumSubset(InterfaceItemBase):
+
+ """Enumeration subset.
+
+ Instance variables:
+ enum -- enumeration
+ allowed_elements -- dictionary of elements of enumeration
+ which are allowed in this subset
+
+ """
+
+ def __init__(self, name, enum, description=None, design_description=None,
+ issues=None, todos=None, platform=None,
+ allowed_elements=None):
+ super(EnumSubset, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform)
+
+ self.enum = enum
+ self.allowed_elements = \
+ allowed_elements if allowed_elements is not None else {}
+
+
+class Param(InterfaceItemBase):
+
+ """Parameter.
+
+ Instance variables:
+ is_mandatory -- boolean value indicating whether
+ this parameter is mandatory
+ param_type -- parameter type
+ default_value -- default value
+
+ """
+
+ def __init__(self, name, param_type, description=None,
+ design_description=None, issues=None, todos=None,
+ platform=None, is_mandatory=True, default_value=None, scope=None):
+ super(Param, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform, default_value=default_value, scope=scope)
+
+ self.is_mandatory = is_mandatory
+ self.param_type = param_type
+ self.default_value = default_value
+
+
+class FunctionParam(Param):
+
+ """Function parameter.
+
+ Instance variables:
+ default_value -- optional default value of this parameter
+
+ """
+
+ def __init__(self, name, param_type, description=None,
+ design_description=None, issues=None, todos=None,
+ platform=None, is_mandatory=True, default_value=None, scope=None):
+ super(FunctionParam, self).__init__(
+ name, param_type=param_type, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform, is_mandatory=is_mandatory, default_value=default_value, scope=scope)
+
+ self.default_value = default_value
+
+
+class Struct(InterfaceItemBase):
+
+ """Structure.
+
+ Instance variables:
+ members -- dictionary of structure members (instances of Param class)
+
+ """
+
+ def __init__(self, name, description=None, design_description=None,
+ issues=None, todos=None, platform=None, members=None, scope=None):
+ super(Struct, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform, scope=scope)
+
+ self.members = \
+ members if members is not None else collections.OrderedDict()
+
+
+class Function(InterfaceItemBase):
+
+ """Function.
+
+ Instance variables:
+ function_id -- function identifier (EnumElement from Enum "FunctionID")
+ message_type -- message type (EnumElement from Enum "messageType")
+ params -- function parameters
+
+ """
+
+ def __init__(self, name, function_id, message_type, description=None,
+ design_description=None, issues=None, todos=None,
+ platform=None, params=None, scope=None):
+ super(Function, self).__init__(
+ name, description=description,
+ design_description=design_description, issues=issues, todos=todos,
+ platform=platform, scope=scope)
+
+ self.function_id = function_id
+ self.message_type = message_type
+ self.params = \
+ params if params is not None else collections.OrderedDict()
+
+
+class Interface(object):
+
+ """Interface.
+
+ Instance variables:
+ enums -- dictionary of enumerations
+ structs -- dictionary of structures
+ functions -- dictionary of functions
+ params -- dictionary of interface parameters (name, version, etc.)
+
+ """
+
+ def __init__(self, enums=None, structs=None, functions=None, params=None):
+ self.enums = enums if enums is not None else collections.OrderedDict()
+ self.structs = \
+ structs if structs is not None else collections.OrderedDict()
+ self.functions = \
+ functions if functions is not None else collections.OrderedDict()
+ self.params = params if params is not None else {}
diff --git a/tools/InterfaceGenerator/generator/__init__.py b/tools/InterfaceGenerator/generator/__init__.py
new file mode 100755
index 0000000000..380e81d9ab
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/__init__.py
@@ -0,0 +1,2 @@
+"""Top-level application package.
+"""
diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py
new file mode 100755
index 0000000000..2b372021c2
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py
@@ -0,0 +1,1684 @@
+"""SmartFactory code generator base.
+
+Base of code generator for SmartFactory that provides SmartSchema object in
+accordance with given internal model.
+
+"""
+# pylint: disable=W0402
+# pylint: disable=C0302
+import codecs
+import collections
+import os
+import string
+import uuid
+
+from generator import Model
+
+
+class GenerateError(Exception):
+
+ """Generate error.
+
+ This exception is raised when SmartFactory generator is unable to create
+ output from given model.
+
+ """
+
+ pass
+
+
+class CodeGenerator(object):
+
+ """Base SmartFactory generator.
+
+ This class provides service which allows to generate pair of *.h and
+ *.cc files by given interface model.
+
+ """
+
+ def __init__(self):
+ """Construct new object."""
+
+ self._generated_structs = []
+ self._structs_add_code = u""
+
+ def generate(self, interface, filename, namespace, destination_dir):
+ """Generate SmartFactory source files.
+
+ Generates source code files at destination directory in
+ accordance with given model in specified namespace.
+
+ Keyword arguments:
+ interface -- model of the interface to generate source code for.
+ filename -- name of initial XML file.
+ namespace -- name of destination namespace.
+ destination_dir -- directory to create source files.
+
+ """
+
+ namespace = unicode(namespace)
+
+ if interface is None:
+ raise GenerateError("Given interface is None.")
+
+ self._generated_structs = []
+ self._structs_add_code = ""
+
+ if "messageType" in interface.enums:
+ interface.enums["messageType"] = self._preprocess_message_type(
+ interface.enums["messageType"])
+
+ if not os.path.exists(destination_dir):
+ os.makedirs(destination_dir)
+
+ namespace_open = u""
+ namespace_close = u""
+
+ if namespace:
+ parts = namespace.split(u"::")
+ for part in parts:
+ namespace_open = u"".join(
+ [namespace_open,
+ self._namespace_open_template.substitute(name=part)])
+ namespace_close = u"".join(
+ [namespace_close,
+ "}} // {0}\n".format(part)])
+
+ class_name = unicode(os.path.splitext(filename)[0])
+ guard = u"__CSMARTFACTORY_{0}_{1}_H__".format(
+ class_name.upper(),
+ unicode(uuid.uuid1().hex.capitalize()))
+ header_file_name = u"".join("{0}.h".format(class_name))
+
+ with codecs.open(os.path.join(destination_dir, header_file_name),
+ encoding="utf-8",
+ mode="w") as f_h:
+ f_h.write(self._h_file_tempalte.substitute(
+ class_name=class_name,
+ guard=guard,
+ namespace_open=namespace_open,
+ enums_content=self._gen_enums(
+ interface.enums.values(),
+ interface.structs.values()),
+ namespace_close=namespace_close))
+
+ self._gen_struct_schema_items(interface.structs.values())
+
+ function_id_items = u""
+ if "FunctionID" in interface.enums:
+ function_id = interface.enums["FunctionID"]
+ function_id_items = u"\n".join(
+ [self._impl_code_loc_decl_enum_insert_template.substitute(
+ var_name="function_id_items",
+ enum=function_id.name,
+ value=x.primary_name)
+ for x in function_id.elements.values()])
+
+ message_type_items = u""
+ if "messageType" in interface.enums:
+ message_type = interface.enums["messageType"]
+ message_type_items = u"\n".join(
+ [self._impl_code_loc_decl_enum_insert_template.substitute(
+ var_name="message_type_items",
+ enum=message_type.name,
+ value=x.primary_name)
+ for x in message_type.elements.values()])
+
+ header_file_name = "".join("{0}_schema.h".format(class_name))
+ guard = u"__CSMARTFACTORY_{0}_{1}_HPP__".format(
+ class_name.upper(),
+ unicode(uuid.uuid1().hex.capitalize()))
+ with codecs.open(os.path.join(destination_dir, header_file_name),
+ encoding="utf-8",
+ mode="w") as f_h:
+ f_h.write(self._hpp_schema_file_tempalte.substitute(
+ class_name=class_name,
+ guard=guard,
+ header_file_name=unicode("".join("{0}.h".format(class_name))),
+ namespace_open=namespace_open,
+ class_content=self._gen_h_class(
+ class_name,
+ interface.params,
+ interface.functions.values(),
+ interface.structs.values()),
+ namespace_close=namespace_close))
+
+ with codecs.open(os.path.join(destination_dir,
+ u"".join("{0}_schema.cc".format(class_name))),
+ encoding="utf-8", mode="w") as f_s:
+ f_s.write(self._cc_file_template.substitute(
+ header_file_name=unicode(header_file_name),
+ namespace=namespace,
+ class_name=class_name,
+ function_id_items=self._indent_code(function_id_items, 1),
+ message_type_items=self._indent_code(message_type_items, 1),
+ struct_schema_items=self._structs_add_code,
+ pre_function_schemas=self._gen_pre_function_schemas(
+ interface.functions.values()),
+ function_schemas=self._gen_function_schemas(
+ interface.functions.values()),
+ init_function_impls=self._gen_function_impls(
+ interface.functions.values(),
+ namespace,
+ class_name),
+ init_structs_impls=self._gen_sturct_impls(
+ interface.structs.values(),
+ namespace,
+ class_name),
+ enum_string_coversions=self._gen_enum_to_str_converters(
+ interface.enums.values(),
+ namespace)))
+
+ def _preprocess_message_type(self, message_type):
+ """Preprocess message_type enum.
+
+ In base class this method is unimplemented and will cause runtime
+ exception. This method must be overridden by the subclasses to
+ return message_type enum after preprocessing.
+
+ Keyword arguments:
+ message_type -- message_type enum to preprocess.
+
+ """
+
+ raise GenerateError("Unexpected call to the unimplemented function.")
+
+ def _gen_enum_to_str_converters(self, enums, namespace):
+ """Generate enum to string converters.
+
+ Generates part of source code with specific enum to string value
+ converting functions.
+
+ Keyword arguments:
+ enums -- list of enums to generate string converting functions.
+ namespace -- namespace to address enums.
+
+ Returns:
+ String value with enum to string converting functions.
+
+ """
+
+ if enums is None:
+ raise GenerateError("Enums is None")
+
+ return u"\n".join([self._enum_to_str_converter_template.substitute(
+ namespace=namespace,
+ enum=x.name,
+ cstringvalues=self._indent_code(self._gen_enum_cstring_values(x), 2),
+ enumvalues=self._indent_code(self._gen_enum_enum_values(x, namespace), 2))
+ for x in enums])
+
+ def _gen_enum_cstring_values(self, enum):
+ """Generate list of c-string representing enum values.
+ Keyword arguments:
+ enum -- enum to generate string mapping.
+ Returns:
+ String value with c-string values.
+ """
+ return u",\n".join(['"' + x.name + '"' for x in enum.elements.values()])
+
+ def _gen_enum_enum_values(self, enum, namespace):
+ """Generate list of all enum values.
+ Keyword arguments:
+ enum -- enum to generate the list.
+ namespace -- namespace to address enum.
+ Returns:
+ String value with enum values.
+ """
+ return u",\n".join([namespace + "::" + enum.name + "::" + x.primary_name for x in enum.elements.values()])
+
+ def _gen_h_class(self, class_name, params, functions, structs):
+ """Generate source code of class for header file.
+
+ Generates source code of class that should be used in the
+ header file.
+
+ Keyword arguments:
+ class_name -- name of the class to generate.
+ params -- class parameters.
+ functions -- list of functions to generate methods for.
+ structs -- structures to generate methods for.
+
+ Returns:
+ String with complete *.h file source code.
+
+ """
+
+ return self._class_h_template.substitute(
+ comment=self._gen_class_comment(class_name, params),
+ class_name=class_name,
+ init_function_decls=self._gen_function_decls(functions),
+ init_struct_decls=self._gen_structs_decls(structs))
+
+ def _gen_structs_decls(self, structs):
+ """Generate method prototypes for structs for header file.
+
+ Generates method prototypes for structs that should be used in the
+ header file.
+
+ Keyword arguments:
+ structs -- list of structs to generate methods for.
+
+ Returns:
+ String with structs init methods declarations source code.
+
+ """
+
+ if structs is None:
+ raise GenerateError("Structs is None")
+
+ return u"\n".join([self._indent_code(
+ self._gen_struct_decl(x), 1) for x in structs])
+
+ def _gen_struct_decl(self, struct):
+ """Generate method prototype for struct for header file.
+
+ Generates method prototype for struct that should be used in the
+ header file.
+
+ Keyword arguments:
+ struct -- struct to generate method for.
+
+ Returns:
+ String with struct inin method declaration source code.
+
+ """
+
+ return self._struct_decl_template.substitute(
+ comment=self._gen_comment(struct),
+ struct_name=struct.name)
+
+ def _gen_function_decls(self, functions):
+ """Generate method prototypes for functions for header file.
+
+ Generates method prototypes for functions that should be used in the
+ header file.
+
+ Keyword arguments:
+ functions -- list of functions to generate methods for.
+
+ Returns:
+ String with function init methods declarations source code.
+
+ """
+
+ if functions is None:
+ raise GenerateError("Functions is None")
+
+ return u"\n".join([self._indent_code(
+ self._gen_function_decl(x), 1) for x in functions])
+
+ def _gen_function_decl(self, function):
+ """Generate method prototype for function for header file.
+
+ Generates method prototype for function that should be used in the
+ header file.
+
+ Keyword arguments:
+ function -- function to generate method for.
+
+ Returns:
+ String with function declaration source code.
+
+ """
+
+ return self._function_decl_template.substitute(
+ comment=self._gen_comment(function),
+ function_id=function.function_id.primary_name,
+ message_type=function.message_type.primary_name)
+
+ def _gen_struct_schema_items(self, structs):
+ """Generate struct schema items initialization code for source file.
+
+ Generates struct schema items initialization code that should be used
+ in the source file.
+
+ Keyword arguments:
+ structs -- list of structs to generate code for.
+
+ Returns:
+ String with struct schema items initialization source code.
+
+ """
+
+ if structs is None:
+ raise GenerateError("Structs is None")
+
+ for struct in structs:
+ self._process_struct(struct)
+
+ def _process_struct(self, struct):
+ """Process struct recursively to provide correct initialization.
+
+ This method create source code for cc file that guarantees that
+ structures are initialized in right order (to resolve all
+ dependencies).
+
+ Keyword arguments:
+ struct -- struct to process.
+
+ """
+
+ if struct.name in self._generated_structs:
+ return
+
+ for member in struct.members.values():
+ self._process_struct_member(member)
+
+ self._structs_add_code = u"\n".join(
+ [self._structs_add_code, self._indent_code(
+ self._gen_struct_schema_item(struct), 1)])
+ self._generated_structs.append(struct.name)
+
+ def _process_struct_member(self, member):
+ """Process struct member recursively to provide correct initialization.
+
+ This method ensures that nested structs (if any) are generated.
+
+ Keyword arguments:
+ member -- struct member to process.
+
+ """
+
+ if type(member.param_type) is Model.Struct:
+ self._ensure_struct_generated(member.param_type)
+
+ def _ensure_struct_generated(self, struct):
+ """Ensure that struct is already generated.
+
+ If struct is already created this method returns otherwise it
+ runs generation of struct to resolve dependency.
+
+ Keyword arguments:
+ struct -- struct to ensure existence.
+
+ """
+
+ if struct.name in self._generated_structs:
+ return
+
+ self._process_struct(struct)
+
+ def _gen_struct_schema_item(self, struct):
+ """Generate struct schema item initialization code for source file.
+
+ Generates struct schema item initialization code that should be used
+ in the source file.
+
+ Keyword arguments:
+ struct -- struct to generate code for.
+
+ Returns:
+ String with struct schema item initialization source code.
+
+ """
+
+ return self._struct_schema_item_template.substitute(name=struct.name)
+
+ def _gen_pre_function_schemas(self, functions):
+ """Generate specific code that goes before schema initialization.
+
+ In base class this function is unimplemented and it will raise an
+ runtime exception. Subclasses must implement this function in order
+ to provide format-specific code that goes before schema initialization.
+
+ Keyword arguments:
+ functions -- list of functions to generate code for.
+
+ """
+
+ raise GenerateError("Unexpected call to the unimplemented function.")
+
+ def _gen_function_schemas(self, functions):
+ """Generate functions initialization code for source file.
+
+ Generates functions schema initialization code that should be used
+ in the source file.
+
+ Keyword arguments:
+ functions -- list of functions to generate code for.
+
+ Returns:
+ String with functions schema initialization source code.
+
+ """
+
+ if functions is None:
+ raise GenerateError("Functions is None")
+
+ return u"".join([self._indent_code(
+ self._gen_function_schema(x), 1)
+ for x in functions])
+
+ def _gen_function_schema(self, function):
+ """Generate function initialization code for source file.
+
+ Generates function schema initialization code that should be used
+ in the source file.
+
+ Keyword arguments:
+ function -- function to generate method for.
+
+ Returns:
+ String with function schema initialization source code.
+
+ """
+
+ return self._function_schema_template.substitute(
+ function_id=function.function_id.primary_name,
+ message_type=function.message_type.primary_name)
+
+ def _gen_sturct_impls(self, structs, namespace, class_name):
+ """Generate structs implementation for source file.
+
+ Generates implementation code of methods that provide schema items for
+ structs. This code should be used in the source file.
+
+ Keyword arguments:
+ structs -- list of structs to generate methods for.
+ namespace -- name of destination namespace.
+ class_name -- name of the parent class.
+
+ Returns:
+ String with structs implementation source code.
+
+ """
+
+ if structs is None:
+ raise GenerateError("Structs is None")
+
+ return u"\n".join([self._gen_struct_impl(
+ x, namespace, class_name) for x in structs])
+
+ def _gen_struct_impl(self, struct, namespace, class_name):
+ """Generate struct implementation for source file.
+
+ Generates implementation code of method that provide schema item for
+ struct. This code should be used in the source file.
+
+ Keyword arguments:
+ struct -- struct to generate method for.
+ namespace -- name of destination namespace.
+ class_name -- name of the parent class.
+
+ Returns:
+ String with structs implementation source code.
+
+ """
+
+ processed_enums = []
+ return self._struct_impl_template.substitute(
+ namespace=namespace,
+ class_name=class_name,
+ struct_name=struct.name,
+ code=self._indent_code(
+ self._struct_impl_code_tempate.substitute(
+ schema_loc_decl=self._gen_schema_loc_decls(
+ struct.members.values(), processed_enums),
+ schema_items_decl=self._gen_schema_items_decls(
+ struct.members.values()),
+ schema_item_fill=self._gen_schema_items_fill(
+ struct.members.values())),
+ 1))
+
+ def _gen_schema_loc_decls(self, members, processed_enums):
+ """Generate local declarations of variables for schema.
+
+ This method generates full set of required variables for
+ enums and enum subsets.
+
+ Keyword arguments:
+ members -- struct/function members/params.
+ processed_enums -- list of already processed enums.
+
+ Returns:
+ String with local declarations source code.
+
+ """
+
+ result = u""
+ for member in members:
+ if type(member.param_type) is Model.Enum and \
+ member.param_type.name not in processed_enums:
+ local_var = self._gen_schema_loc_emum_var_name(
+ member.param_type)
+ result = u"\n".join(
+ [u"".join(
+ [result, self._impl_code_loc_decl_enum_template.
+ substitute(
+ type=member.param_type.name,
+ var_name=local_var)]),
+ u"\n".join(
+ [self._impl_code_loc_decl_enum_insert_template.
+ substitute(
+ var_name=local_var,
+ enum=member.param_type.name,
+ value=x.primary_name)
+ for x in member.param_type.elements.values()])])
+ processed_enums.append(member.param_type.name)
+ result = u"".join([result, u"\n\n"]) if result else u""
+ elif type(member.param_type) is Model.EnumSubset:
+ local_var = self._gen_schema_loc_emum_s_var_name(member.name)
+ result = u"\n".join(
+ [u"".join(
+ [result, self._impl_code_loc_decl_enum_template.
+ substitute(
+ type=member.param_type.enum.name,
+ var_name=local_var)]),
+ u"\n".join(
+ [self._impl_code_loc_decl_enum_insert_template.
+ substitute(
+ var_name=local_var,
+ enum=member.param_type.enum.name,
+ value=x.primary_name)
+ for x in member.param_type.
+ allowed_elements.values()])])
+ result = u"".join([result, u"\n\n"]) if result else u""
+ elif type(member.param_type) is Model.Array:
+ result = u"".join(
+ [result, self._gen_schema_loc_decls(
+ [Model.Param(name=member.param_type.element_type.name
+ if type(member.param_type.element_type) is
+ Model.EnumSubset else "",
+ param_type=member.param_type.element_type)],
+ processed_enums)])
+
+ return result
+
+ def _gen_schema_items_decls(self, members):
+ """Generate schema items declarations.
+
+ Generates declaration and initialization of schema items
+ which is uses as struct members/function parameters.
+
+ Keyword arguments:
+ members -- list of struct members/function parameters.
+
+ Returns:
+ String with schema items declaration source code.
+
+ """
+
+ result = u"\n\n".join(
+ [self._gen_schema_item_decl(x) for x in members])
+
+ return u"".join([result, u"\n\n"]) if result else u""
+
+ def _gen_schema_item_decl(self, member):
+ """Generate schema item declaration.
+
+ Generates declaration and initialization of schema item
+ which is uses as struct member/function parameter.
+
+ Keyword arguments:
+ member -- struct member/function parameter.
+
+ Returns:
+ String with schema item declaration source code.
+
+ """
+
+ return self._impl_code_item_decl_temlate.substitute(
+ comment=self._gen_comment(member, False),
+ var_name=self._gen_schema_item_var_name(member),
+ item_decl=self._gen_schema_item_decl_code(
+ member.param_type,
+ member.name,
+ member.default_value))
+
+ def _gen_schema_item_decl_code(self, param, member_name, default_value):
+
+ """Generate schema item initialization code.
+
+ Generates type-specific code that initializes schema item
+
+ Keyword arguments:
+ param -- value of parameter type.
+ mamber_name -- name of struct member/function parameter.
+ default_value -- default value (used only for function parameters).
+
+ Returns:
+ String with schema item initialization source code.
+
+ """
+ code = u""
+ if type(param) is Model.Boolean:
+ code = self._impl_code_bool_item_template.substitute(
+ params=self._gen_schema_item_param_values(
+ [[u"bool", None if param.default_value is None
+ else u"true" if param.default_value is True else u"false"]]))
+ elif type(param) is Model.Integer:
+ if param.max_value < 2 ** 31:
+ code = self._impl_code_integer_item_template.substitute(
+ type=u"int32_t",
+ params=self._gen_schema_item_param_values(
+ [[u"int32_t", param.min_value],
+ [u"int32_t", param.max_value],
+ [u"int32_t", param.default_value]]))
+ elif param.max_value < 2 ** 63:
+ code = self._impl_code_integer_item_template.substitute(
+ type=u"int64_t",
+ params=self._gen_schema_item_param_values(
+ [[u"int64_t", param.min_value],
+ [u"int64_t", str(param.max_value) + u"LL"],
+ [u"int64_t", param.default_value]]))
+ else:
+ raise GenerateError("Parameter value too large: " + str(param.max_value))
+ elif type(param) is Model.Double:
+ code = self._impl_code_integer_item_template.substitute(
+ type=u"double",
+ params=self._gen_schema_item_param_values(
+ [[u"double", param.min_value],
+ [u"double", param.max_value],
+ [u"double", param.default_value]]))
+ elif type(param) is Model.String:
+ code = self._impl_code_string_item_template.substitute(
+ params=self._gen_schema_item_param_values(
+ [[u"size_t", param.min_length],
+ [u"size_t", param.max_length],
+ [u"std::string", u"".join(
+ [u'"', param.default_value, u'"']) if param.default_value
+ is not None else u""]]))
+ elif type(param) is Model.Array:
+ code = self._impl_code_array_item_template.substitute(
+ params=u"".join(
+ [u"".join(
+ [self._gen_schema_item_decl_code(
+ param.element_type,
+ param.element_type.name if type(param.element_type)
+ is Model.EnumSubset else u"",
+ None),
+ u", "]),
+ self._gen_schema_item_param_values(
+ [[u"size_t", param.min_size],
+ [u"size_t", param.max_size]])]))
+ elif type(param) is Model.Struct:
+ code = self._impl_code_struct_item_template.substitute(
+ name=param.name)
+ elif type(param) is Model.Enum:
+ code = self._impl_code_enum_item_template.substitute(
+ type=param.name,
+ params=u"".join(
+ [self._gen_schema_loc_emum_var_name(param),
+ u", ",
+ self._gen_schema_item_param_values(
+ [[u"".join([param.name, u"::eType"]),
+ u"".join([param.name, u"::",
+ default_value.primary_name]) if
+ default_value is not None else None]])]))
+ elif type(param) is Model.EnumSubset:
+ code = self._impl_code_enum_item_template.substitute(
+ type=param.enum.name,
+ params=u"".join(
+ [self._gen_schema_loc_emum_s_var_name(member_name),
+ u", ",
+ self._gen_schema_item_param_values(
+ [[u"".join([param.enum.name, u"::eType"]),
+ default_value.primary_name if default_value
+ is not None else None]])]))
+ else:
+ raise GenerateError("Unexpected type of parameter: " +
+ str(type(param)))
+ return code
+
+ def _gen_schema_item_param_values(self, params):
+ """Generate values of schema item initialization parameters.
+
+ Generates part of code which is used as schema item initialization
+ parameters.
+
+ Keyword arguments:
+ params -- list of tuples which maps parameter type to parameter value.
+
+ Returns:
+ String with schema item initialization parameters source code.
+
+ """
+
+ result = u""
+ for param in params:
+ value = self._impl_code_item_param_value_template.substitute(
+ type=param[0],
+ value=str(param[1] if param[1] is not None else ""))
+ result = u"".join([result, u"".join(
+ [u", ", value])
+ if result else value])
+
+ return result
+
+ def _gen_schema_items_fill(self, members):
+ """Generate schema items fill code.
+
+ Generates source code that fills new schema with items.
+
+ Keyword arguments:
+ members -- list of struct members/function parameters to process.
+
+ Returns:
+ String with function schema items fill code.
+
+ """
+
+ result = u"\n".join(
+ [self._gen_schema_item_fill(x) for x in members])
+
+ return u"".join([result, u"\n\n"]) if result else u""
+
+ def _gen_schema_params_fill(self, message_type_name):
+ """Generate schema params fill code.
+
+ In the base class this method is not implemented (raises exception).
+ This method must be implemented by the subclasses to specify format
+ specific PARAMS for the function.
+
+ Keyword arguments:
+ message_type_name -- Name of the messageType enum element.
+
+ Returns:
+ String with function schema params fill code.
+
+ """
+
+ raise GenerateError("Unexpected call to the unimplemented function.")
+
+ def _gen_schema_item_fill(self, member):
+ """Generate schema item fill code.
+
+ Generates source code that fills new schema with item.
+
+ Keyword arguments:
+ member -- struct member/function parameter to process.
+
+ Returns:
+ String with schema item fill code.
+
+ """
+
+ return self._impl_code_item_fill_template.substitute(
+ name=member.name,
+ var_name=self._gen_schema_item_var_name(member),
+ is_mandatory=u"true" if member.is_mandatory is True else u"false")
+
+ @staticmethod
+ def _gen_schema_item_var_name(member):
+ """Generate schema item variable name.
+
+ Generates variable name for local declarations.
+
+ Keyword arguments:
+ member -- struct member/function parameter to process.
+
+ Returns:
+ String with schema item variable name.
+
+ """
+
+ return u"".join([member.name, u"_SchemaItem"])
+
+ @staticmethod
+ def _gen_schema_loc_emum_var_name(param_type):
+ """Generate name of enum local variable.
+
+ Generates name of local variable that defines allowed enum elements.
+
+ Keyword arguments:
+ param_type -- parameter type object.
+
+ Returns:
+ String with name of enum local variable.
+
+ """
+
+ return u"".join([param_type.name, u"_all_enum_values"])
+
+ @staticmethod
+ def _gen_schema_loc_emum_s_var_name(member_name):
+ """Generate name of enum subset local variable.
+
+ Generates name of local variable that defines allowed enum
+ subset elements.
+
+ Keyword arguments:
+ param_type -- parameter type object.
+
+ Returns:
+ String with name of enum subset local variable.
+
+ """
+
+ return u"".join([member_name, "_allowed_enum_subset_values"])
+
+ def _gen_function_impls(self, functions, namespace, class_name):
+ """Generate functions implementation for source file.
+
+ Generates implementation code of methods that provide schema for
+ functions. This code should be used in the source file.
+
+ Keyword arguments:
+ functions -- list of functions to generate methods for.
+ namespace -- name of destination namespace.
+ class_name -- name of the parent class.
+
+ Returns:
+ String with functions implementation source code.
+
+ """
+
+ if functions is None:
+ raise GenerateError("Functions is None")
+
+ return u"\n".join([self._gen_function_impl(
+ x, namespace, class_name) for x in functions])
+
+ def _gen_function_impl(self, function, namespace, class_name):
+ """Generate function implementation for source file.
+
+ Generates implementation code of method that provides schema for
+ function. This code should be used in the source file.
+
+ Keyword arguments:
+ function -- function to generate method for.
+ namespace -- name of destination namespace.
+ class_name -- name of the parent class.
+
+ Returns:
+ String with function implementation source code.
+
+ """
+
+ processed_enums = []
+ return self._function_impl_template.substitute(
+ namespace=namespace,
+ class_name=class_name,
+ function_id=function.function_id.primary_name,
+ message_type=function.message_type.primary_name,
+ code=self._indent_code(
+ self._function_impl_code_tempate.substitute(
+ schema_loc_decl=self._gen_schema_loc_decls(
+ function.params.values(), processed_enums),
+ schema_items_decl=self._gen_schema_items_decls(
+ function.params.values()),
+ schema_item_fill=self._gen_schema_items_fill(
+ function.params.values()),
+ schema_params_fill=self._gen_schema_params_fill(
+ function.message_type.name)),
+ 1))
+
+ def _gen_enums(self, enums, structs):
+ """Generate enums for header file.
+
+ Generates declaration of enumerations for the header file.
+
+ Keyword arguments:
+ enums -- list of enums to generate.
+
+ Returns:
+ String with enums declaration source code.
+
+ """
+
+ if enums is None:
+ raise GenerateError("Enums is None")
+
+ if structs is None:
+ raise GenerateError("Structs is None")
+
+ if structs:
+ struct_id_enum_elements = collections.OrderedDict()
+ for struct in structs:
+ struct_id_enum_elements[struct.name] = Model.EnumElement(
+ name=struct.name)
+ return u"\n".join(
+ [self._gen_enum(
+ Model.Enum(name="StructIdentifiers",
+ elements=struct_id_enum_elements)),
+ u"\n".join([self._gen_enum(x) for x in enums])])
+
+ return u"\n".join([self._gen_enum(x) for x in enums])
+
+ def _gen_enum(self, enum):
+ """Generate enum for header file.
+
+ Generates declaration of enumeration for the header file.
+
+ Keyword arguments:
+ enum -- enum to generate.
+
+ Returns:
+ String with enum declaration source code.
+
+ """
+
+ enum_elements = enum.elements.values()
+ enum_elements.insert(0, Model.EnumElement(
+ name=u"INVALID_ENUM",
+ description=None,
+ design_description=None,
+ issues=None,
+ todos=None,
+ platform=None,
+ internal_name=None,
+ value=u"-1"))
+ return self._enum_template.substitute(
+ comment=self._gen_comment(enum),
+ name=enum.name,
+ enum_items=self._indent_code(self._gen_enum_elements(
+ enum_elements), 1))
+
+ def _gen_enum_elements(self, enum_elements):
+ """Generate enum elements for header file.
+
+ Generates declaration of enumeration elements for the header file.
+
+ Keyword arguments:
+ enum_elements -- list of enum elements to generate.
+
+ Returns:
+ String with enum elements declaration source code.
+
+ """
+
+ return u",\n\n".join([self._gen_enum_element(x)
+ for x in enum_elements])
+
+ def _gen_enum_element(self, enum_element):
+ """Generate enum element for header file.
+
+ Generates declaration of enumeration element for the header file.
+
+ Keyword arguments:
+ enum_element -- enum element to generate.
+
+ Returns:
+ String with enum element declaration source code.
+
+ """
+
+ if enum_element.value is not None:
+ return self._enum_element_with_value_template.substitute(
+ comment=self._gen_comment(enum_element),
+ name=enum_element.primary_name,
+ value=enum_element.value)
+ else:
+ return self._enum_element_with_no_value_template.substitute(
+ comment=self._gen_comment(enum_element),
+ name=enum_element.primary_name)
+
+ def _gen_class_comment(self, class_name, params):
+ """Generate doxygen comment to the class for header file.
+
+ Generates doxygen comment for the class that should be used in
+ the header file.
+
+ Keyword arguments:
+ class_name -- name of the class.
+ params -- class parameters.
+
+ Returns:
+ String with generated doxygen class comment.
+
+ """
+
+ return self._class_comment_template.substitute(
+ class_name=class_name,
+ class_params=u"".join(
+ [u" * {0} - {1}\n".format(x[0],
+ x[1]) for x in params.items()])
+ if params else u" * none\n")
+
+ def _gen_comment(self, interface_item_base, use_doxygen=True):
+ """Generate doxygen comment for iterface_item_base for header file.
+
+ Generates doxygen comment for any iterface_item_base for the header
+ file.
+
+ Keyword arguments:
+ interface_item_base -- object to generate doxygen comment for.
+ use_doxygen -- Flag that indicates does function uses doxygen or not.
+
+ Returns:
+ String with generated doxygen comment.
+
+ """
+
+ brief_type_title = None
+ interface_item_base_classname = interface_item_base.__class__.__name__
+ if interface_item_base_classname in self._model_types_briefs:
+ brief_type_title = \
+ self._model_types_briefs[interface_item_base_classname]
+ else:
+ raise GenerateError("Unable to create comment for unknown type " +
+ interface_item_base_classname)
+
+ name = interface_item_base.primary_name if \
+ type(interface_item_base) is Model.EnumElement else \
+ interface_item_base.name
+ brief_description = (u" * @brief {0}{1}.\n" if use_doxygen is
+ True else u"// {0}{1}.\n").format(
+ brief_type_title,
+ name)
+
+ description = u"".join([(u" * {0}\n" if use_doxygen
+ is True else u"// {0}\n").format(x)
+ for x in self._normalize_multiline_comments(
+ interface_item_base.description)])
+ if description is not u"":
+ description = u"".join([u" *\n" if use_doxygen
+ is True else u"//\n", description])
+
+ design_description = u"".join([(u" * {0}\n" if use_doxygen is
+ True else u"// {0}\n").format(x)
+ for x in
+ self._normalize_multiline_comments(
+ interface_item_base.
+ design_description)])
+ if design_description is not u"":
+ design_description = u"".join([u" *\n" if use_doxygen is
+ True else "//\n",
+ design_description])
+
+ issues = u"".join([(u" * @note {0}\n" if use_doxygen is
+ True else u"// Note: {0}\n").format(x)
+ for x in self._normalize_multiline_comments(
+ [x.value for x in interface_item_base.issues])])
+ if issues is not u"":
+ issues = u"".join([u" *\n" if use_doxygen is
+ True else u"//\n", issues])
+
+ todos = u"".join([(u" * @todo {0}\n" if use_doxygen is
+ True else u"// ToDo: {0}\n").format(x)
+ for x in self._normalize_multiline_comments(
+ interface_item_base.todos)])
+ if todos is not u"":
+ todos = u"".join([u" *\n" if use_doxygen is
+ True else u"//\n", todos])
+
+ returns = u""
+ if type(interface_item_base) is Model.Function:
+ returns = u"".join([u" *\n", self._function_return_comment])
+
+ template = self._comment_doxygen_template if use_doxygen is \
+ True else self._comment_cc_template
+
+ return template.substitute(
+ brief_description=brief_description,
+ description=description,
+ design_description=design_description,
+ issues=issues,
+ todos=todos,
+ returns=returns)
+
+ def _indent_code(self, code, indent_level):
+ """Indent given source code.
+
+ Indents given source code right by given indentation level.
+
+ Keyword arguments:
+ code -- given source code.
+ indent_level -- desired indentation level.
+
+ Returns:
+ String with processed code.
+
+ """
+
+ code_lines = code.split("\n")
+ return u"".join(
+ [u"{0}{1}\n".format(
+ self._indent_template * indent_level,
+ x) if x is not u"" else u"\n" for x in code_lines])
+
+ @staticmethod
+ def _normalize_multiline_comments(initial_strings):
+ """Normalize multiline comments.
+
+ Makes multiline comment clean of any line breaks creating additional
+ strings for the comment.
+
+ Keyword arguments:
+ initial_strings -- initial list of strings to process.
+
+ Returns:
+ New list of the strings (with contains no strings with line breaks).
+
+ """
+
+ result = []
+ for initial_string in initial_strings:
+ result = result + initial_string.splitlines()
+ return result
+
+ _model_types_briefs = dict(
+ {u"EnumElement": u"",
+ u"Enum": u"Enumeration ",
+ u"Function": u"Method that generates schema for function ",
+ u"Struct": u"Method that generates schema item for structure ",
+ u"Param": u"Struct member ",
+ u"FunctionParam": u"Function parameter "})
+
+ _h_file_tempalte = string.Template(
+ u'''/**\n'''
+ u''' * @file ${class_name}.h\n'''
+ u''' * @brief Generated class ${class_name} header file.\n'''
+ u''' *\n'''
+ u''' * This class is a part of SmartObjects solution. It provides\n'''
+ u''' * factory functionallity which allows client to use '''
+ u'''SmartSchemas\n'''
+ u''' * in accordance with definitions from ${class_name}.xml file\n'''
+ u''' */\n'''
+ u'''// Copyright (c) 2013, Ford Motor Company\n'''
+ u'''// All rights reserved.\n'''
+ u'''//\n'''
+ u'''// Redistribution and use in source and binary forms, '''
+ u'''with or without\n'''
+ u'''// modification, are permitted provided that the following '''
+ u'''conditions are met:\n'''
+ u'''//\n'''
+ u'''// Redistributions of source code must retain the above '''
+ u'''copyright notice, this\n'''
+ u'''// list of conditions and the following disclaimer.\n'''
+ u'''//\n'''
+ u'''// Redistributions in binary form must reproduce '''
+ u'''the above copyright notice,\n'''
+ u'''// this list of conditions and the following\n'''
+ u'''// disclaimer in the documentation and/or other materials '''
+ u'''provided with the\n'''
+ u'''// distribution.\n'''
+ u'''//\n'''
+ u'''// Neither the name of the Ford Motor Company nor the names '''
+ u'''of its contributors\n'''
+ u'''// may be used to endorse or promote products derived '''
+ u'''from this software\n'''
+ u'''// without specific prior written permission.\n'''
+ u'''//\n'''
+ u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND '''
+ u'''CONTRIBUTORS "AS IS"\n'''
+ u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT '''
+ u'''LIMITED TO, THE\n'''
+ u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR '''
+ u'''A PARTICULAR PURPOSE\n'''
+ u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER '''
+ u'''OR CONTRIBUTORS BE\n'''
+ u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, '''
+ u'''EXEMPLARY, OR\n'''
+ u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, '''
+ u'''PROCUREMENT OF\n'''
+ u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; '''
+ u'''OR BUSINESS\n'''
+ u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, '''
+ u'''WHETHER IN\n'''
+ u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE '''
+ u'''OR OTHERWISE)\n'''
+ u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF '''
+ u'''ADVISED OF THE\n'''
+ u'''// POSSIBILITY OF SUCH DAMAGE.\n\n'''
+ u'''#ifndef $guard\n'''
+ u'''#define $guard\n'''
+ u'''\n'''
+ u'''$namespace_open'''
+ u'''$enums_content'''
+ u'''$namespace_close'''
+ u'''#endif //$guard\n'''
+ u'''\n\n''')
+
+ _hpp_schema_file_tempalte = string.Template(
+ u'''/**\n'''
+ u''' * @file ${class_name}.hpp\n'''
+ u''' * @brief Generated class ${class_name} header file.\n'''
+ u''' *\n'''
+ u''' * This class is a part of SmartObjects solution. It provides\n'''
+ u''' * factory functionallity which allows client to use '''
+ u'''SmartSchemas\n'''
+ u''' * in accordance with definitions from ${class_name}.xml file\n'''
+ u''' */\n'''
+ u'''// Copyright (c) 2013, Ford Motor Company\n'''
+ u'''// All rights reserved.\n'''
+ u'''//\n'''
+ u'''// Redistribution and use in source and binary forms, '''
+ u'''with or without\n'''
+ u'''// modification, are permitted provided that the following '''
+ u'''conditions are met:\n'''
+ u'''//\n'''
+ u'''// Redistributions of source code must retain the above '''
+ u'''copyright notice, this\n'''
+ u'''// list of conditions and the following disclaimer.\n'''
+ u'''//\n'''
+ u'''// Redistributions in binary form must reproduce '''
+ u'''the above copyright notice,\n'''
+ u'''// this list of conditions and the following\n'''
+ u'''// disclaimer in the documentation and/or other materials '''
+ u'''provided with the\n'''
+ u'''// distribution.\n'''
+ u'''//\n'''
+ u'''// Neither the name of the Ford Motor Company nor the names '''
+ u'''of its contributors\n'''
+ u'''// may be used to endorse or promote products derived '''
+ u'''from this software\n'''
+ u'''// without specific prior written permission.\n'''
+ u'''//\n'''
+ u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND '''
+ u'''CONTRIBUTORS "AS IS"\n'''
+ u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT '''
+ u'''LIMITED TO, THE\n'''
+ u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR '''
+ u'''A PARTICULAR PURPOSE\n'''
+ u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER '''
+ u'''OR CONTRIBUTORS BE\n'''
+ u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, '''
+ u'''EXEMPLARY, OR\n'''
+ u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, '''
+ u'''PROCUREMENT OF\n'''
+ u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; '''
+ u'''OR BUSINESS\n'''
+ u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, '''
+ u'''WHETHER IN\n'''
+ u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE '''
+ u'''OR OTHERWISE)\n'''
+ u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF '''
+ u'''ADVISED OF THE\n'''
+ u'''// POSSIBILITY OF SUCH DAMAGE.\n\n'''
+ u'''#ifndef $guard\n'''
+ u'''#define $guard\n'''
+ u'''\n'''
+ u'''#include "formatters/CSmartFactory.hpp"\n'''
+ u'''#include "smart_objects/smart_schema.h"\n'''
+ u'''#include "smart_objects/schema_item.h"\n'''
+ u'''#include "utils/shared_ptr.h"\n'''
+ u'''#include "$header_file_name"\n'''
+ u'''\n'''
+ u'''$namespace_open'''
+ u'''\n\n'''
+ u'''$class_content'''
+ u'''\n\n'''
+ u'''$namespace_close'''
+ u'''\n'''
+ u'''#endif //$guard\n'''
+ u'''\n''')
+
+ _namespace_open_template = string.Template(
+ u'''namespace $name {\n''')
+
+ _cc_file_template = string.Template(
+ u'''/**\n'''
+ u''' * @file ${class_name}.cc\n'''
+ u''' * @brief Generated class ${class_name} source file.\n'''
+ u''' *\n'''
+ u''' * This class is a part of SmartObjects solution. It provides\n'''
+ u''' * factory functionallity which allows client to use '''
+ u'''SmartSchemas\n'''
+ u''' * in accordance with definitions from ${class_name}.xml file\n'''
+ u''' */\n'''
+ u'''// Copyright (c) 2013, Ford Motor Company\n'''
+ u'''// All rights reserved.\n'''
+ u'''//\n'''
+ u'''// Redistribution and use in source and binary forms, '''
+ u'''with or without\n'''
+ u'''// modification, are permitted provided that the following '''
+ u'''conditions are met:\n'''
+ u'''//\n'''
+ u'''// Redistributions of source code must retain the above '''
+ u'''copyright notice, this\n'''
+ u'''// list of conditions and the following disclaimer.\n'''
+ u'''//\n'''
+ u'''// Redistributions in binary form must reproduce '''
+ u'''the above copyright notice,\n'''
+ u'''// this list of conditions and the following\n'''
+ u'''// disclaimer in the documentation and/or other materials '''
+ u'''provided with the\n'''
+ u'''// distribution.\n'''
+ u'''//\n'''
+ u'''// Neither the name of the Ford Motor Company nor the names '''
+ u'''of its contributors\n'''
+ u'''// may be used to endorse or promote products derived '''
+ u'''from this software\n'''
+ u'''// without specific prior written permission.\n'''
+ u'''//\n'''
+ u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND '''
+ u'''CONTRIBUTORS "AS IS"\n'''
+ u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT '''
+ u'''LIMITED TO, THE\n'''
+ u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR '''
+ u''''A PARTICULAR PURPOSE\n'''
+ u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER '''
+ u'''OR CONTRIBUTORS BE\n'''
+ u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, '''
+ u'''EXEMPLARY, OR\n'''
+ u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, '''
+ u'''PROCUREMENT OF\n'''
+ u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; '''
+ u'''OR BUSINESS\n'''
+ u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, '''
+ u'''WHETHER IN\n'''
+ u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE '''
+ u'''OR OTHERWISE)\n'''
+ u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF '''
+ u'''ADVISED OF THE\n'''
+ u'''// POSSIBILITY OF SUCH DAMAGE.\n\n'''
+ u'''#include <map>\n'''
+ u'''#include <set>\n'''
+ u'''\n'''
+ u'''#include "$header_file_name"\n'''
+ u'''#include "smart_objects/always_true_schema_item.h"\n'''
+ u'''#include "smart_objects/always_false_schema_item.h"\n'''
+ u'''#include "smart_objects/array_schema_item.h"\n'''
+ u'''#include "smart_objects/bool_schema_item.h"\n'''
+ u'''#include "smart_objects/object_schema_item.h"\n'''
+ u'''#include "smart_objects/string_schema_item.h"\n'''
+ u'''#include "smart_objects/enum_schema_item.h"\n'''
+ u'''#include "smart_objects/number_schema_item.h"\n'''
+ u'''#include "smart_objects/schema_item_parameter.h"\n'''
+ u'''\n'''
+ u'''using namespace NsSmartDeviceLink::NsSmartObjects;\n'''
+ u'''\n'''
+ u'''$namespace::$class_name::$class_name()\n'''
+ u''' : NsSmartDeviceLink::NsJSONHandler::CSmartFactory<FunctionID::eType, '''
+ u'''messageType::eType, StructIdentifiers::eType>() {\n'''
+ u''' TStructsSchemaItems struct_schema_items;\n'''
+ u''' InitStructSchemes(struct_schema_items);\n'''
+ u'''\n'''
+ u''' std::set<FunctionID::eType> function_id_items;\n'''
+ u'''${function_id_items}'''
+ u'''\n'''
+ u''' std::set<messageType::eType> message_type_items;\n'''
+ u'''${message_type_items}'''
+ u'''\n'''
+ u''' InitFunctionSchemes(struct_schema_items, function_id_items, '''
+ u'''message_type_items);\n'''
+ u'''}\n'''
+ u'''\n'''
+ u'''utils::SharedPtr<ISchemaItem> $namespace::$class_name::'''
+ u'''ProvideObjectSchemaItemForStruct(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const StructIdentifiers::eType struct_id) {\n'''
+ u''' const TStructsSchemaItems::const_iterator it = '''
+ u'''struct_schema_items.find(struct_id);\n'''
+ u''' if (it != struct_schema_items.end()) {\n'''
+ u''' return it->second;\n'''
+ u''' }\n'''
+ u'''\n'''
+ u''' return NsSmartDeviceLink::NsSmartObjects::'''
+ u'''CAlwaysFalseSchemaItem::create();\n'''
+ u'''}\n'''
+ u'''\n'''
+ u'''void $namespace::$class_name::InitStructSchemes(\n'''
+ u''' TStructsSchemaItems &struct_schema_items) {'''
+ u'''$struct_schema_items'''
+ u'''}\n'''
+ u'''\n'''
+ u'''void $namespace::$class_name::InitFunctionSchemes(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const std::set<FunctionID::eType> &function_id_items,\n'''
+ u''' const std::set<messageType::eType> &message_type_items) {\n'''
+ u'''$pre_function_schemas'''
+ u'''$function_schemas'''
+ u'''}\n'''
+ u'''\n'''
+ u'''//------------- Functions schemes initialization -------------\n'''
+ u'''\n'''
+ u'''$init_function_impls'''
+ u'''\n'''
+ u'''//----------- Structs schema items initialization ------------\n'''
+ u'''\n'''
+ u'''$init_structs_impls'''
+ u'''\n'''
+ u'''//-------------- String to value enum mapping ----------------\n'''
+ u'''\n'''
+ u'''namespace NsSmartDeviceLink {\n'''
+ u'''namespace NsSmartObjects {\n'''
+ u'''\n'''
+ u'''$enum_string_coversions'''
+ u'''\n'''
+ u'''} // NsSmartObjects\n'''
+ u'''} // NsSmartDeviceLink\n'''
+ u'''\n''')
+
+ _enum_to_str_converter_template = string.Template(
+ u'''template<>\n'''
+ u'''const EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''EnumToCStringMap\n'''
+ u'''EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''enum_to_cstring_map_ =\n'''
+ u''' EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''InitEnumToCStringMap();\n'''
+ u'''\n'''
+ u'''template<>\n'''
+ u'''const EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''CStringToEnumMap\n'''
+ u'''EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''cstring_to_enum_map_ =\n'''
+ u''' EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''InitCStringToEnumMap();\n'''
+ u'''\n'''
+ u'''template<>\n'''
+ u'''const char* const\n'''
+ u'''EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''cstring_values_[] = {\n'''
+ u'''${cstringvalues}'''
+ u'''};\n'''
+ u'''\n'''
+ u'''template<>\n'''
+ u'''const ${namespace}::${enum}::eType\n'''
+ u'''EnumConversionHelper<${namespace}::${enum}::eType>::'''
+ u'''enum_values_[] = {\n'''
+ u'''${enumvalues}'''
+ u'''};\n'''
+ u'''\n''')
+
+ _struct_schema_item_template = string.Template(
+ u'''utils::SharedPtr<ISchemaItem> struct_schema_item_${name} = '''
+ u'''InitStructSchemaItem_${name}(struct_schema_items);\n'''
+ u'''struct_schema_items.insert(std::make_pair('''
+ u'''StructIdentifiers::${name}, struct_schema_item_${name}));\n'''
+ u'''structs_schemes_.insert(std::make_pair('''
+ u'''StructIdentifiers::${name}, CSmartSchema('''
+ u'''struct_schema_item_${name})));''')
+
+ _function_schema_template = string.Template(
+ u'''functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::'''
+ u'''NsJSONHandler::'''
+ u'''SmartSchemaKey<FunctionID::eType, messageType::eType>'''
+ u'''(FunctionID::$function_id, messageType::$message_type), '''
+ u'''InitFunction_${function_id}_${message_type}('''
+ u'''struct_schema_items, function_id_items, message_type_items)));''')
+
+ _struct_impl_template = string.Template(
+ u'''utils::SharedPtr<ISchemaItem> $namespace::$class_name::'''
+ u'''InitStructSchemaItem_${struct_name}(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items) {\n'''
+ u'''$code'''
+ u'''}\n''')
+
+ _struct_impl_code_tempate = string.Template(
+ u'''${schema_loc_decl}'''
+ u'''${schema_items_decl}'''
+ u'''CObjectSchemaItem::Members '''
+ u'''schema_members;\n\n'''
+ u'''${schema_item_fill}'''
+ u'''return CObjectSchemaItem::create(schema_members);''')
+
+ _impl_code_loc_decl_enum_template = string.Template(
+ u'''std::set<${type}::eType> ${var_name};''')
+
+ _impl_code_loc_decl_enum_insert_template = string.Template(
+ u'''${var_name}.insert(${enum}::${value});''')
+
+ _impl_code_item_decl_temlate = string.Template(
+ u'''${comment}'''
+ u'''utils::SharedPtr<ISchemaItem> ${var_name} = ${item_decl};''')
+
+ _impl_code_integer_item_template = string.Template(
+ u'''TNumberSchemaItem<${type}>::create(${params})''')
+
+ _impl_code_bool_item_template = string.Template(
+ u'''CBoolSchemaItem::create(${params})''')
+
+ _impl_code_string_item_template = string.Template(
+ u'''CStringSchemaItem::create(${params})''')
+
+ _impl_code_array_item_template = string.Template(
+ u'''CArraySchemaItem::create(${params})''')
+
+ _impl_code_struct_item_template = string.Template(
+ u'''ProvideObjectSchemaItemForStruct(struct_schema_items, '''
+ u'''StructIdentifiers::${name})''')
+
+ _impl_code_enum_item_template = string.Template(
+ u'''TEnumSchemaItem<${type}::eType>::create(${params})''')
+
+ _impl_code_item_param_value_template = string.Template(
+ u'''TSchemaItemParameter<$type>($value)''')
+
+ _impl_code_item_fill_template = string.Template(
+ u'''schema_members["${name}"] = CObjectSchemaItem::'''
+ u'''SMember(${var_name}, ${is_mandatory});''')
+
+ _function_impl_template = string.Template(
+ u'''CSmartSchema $namespace::$class_name::'''
+ u'''InitFunction_${function_id}_${message_type}(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const std::set<FunctionID::eType> &function_id_items,\n'''
+ u''' const std::set<messageType::eType> &message_type_items) {\n'''
+ u'''$code'''
+ u'''}\n''')
+
+ _function_impl_code_tempate = string.Template(
+ u'''${schema_loc_decl}'''
+ u'''${schema_items_decl}'''
+ u'''CObjectSchemaItem::Members '''
+ u'''schema_members;\n\n'''
+ u'''${schema_item_fill}'''
+ u'''CObjectSchemaItem::Members '''
+ u'''params_members;\n'''
+ u'''${schema_params_fill}'''
+ u'''\n'''
+ u'''CObjectSchemaItem::Members '''
+ u'''root_members_map;\n'''
+ u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_MSG_PARAMS] = '''
+ u'''CObjectSchemaItem::SMember(CObjectSchemaItem::'''
+ u'''create(schema_members), true);\n'''
+ u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PARAMS] = '''
+ u'''CObjectSchemaItem::SMember(CObjectSchemaItem::'''
+ u'''create(params_members), true);\n\n'''
+ u'''return CSmartSchema(CObjectSchemaItem::'''
+ u'''create(root_members_map));''')
+
+ _class_h_template = string.Template(
+ u'''$comment\n'''
+ u'''class $class_name : public NsSmartDeviceLink::NsJSONHandler::'''
+ u'''CSmartFactory<FunctionID::eType, messageType::eType, '''
+ u'''StructIdentifiers::eType> {\n'''
+ u''' public:\n'''
+ u''' /**\n'''
+ u''' * @brief Constructor.\n'''
+ u''' */\n'''
+ u''' $class_name();\n'''
+ u'''\n'''
+ u''' protected:\n'''
+ u''' /**\n'''
+ u''' * @brief Type that maps of struct IDs to schema items.\n'''
+ u''' */\n'''
+ u''' typedef std::map<const StructIdentifiers::eType, '''
+ u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::'''
+ u'''ISchemaItem> > TStructsSchemaItems;\n'''
+ u'''\n'''
+ u''' /**\n'''
+ u''' * @brief Helper that allows to make reference to struct\n'''
+ u''' *\n'''
+ u''' * @param struct_schema_items Struct schema items.\n'''
+ u''' * @param struct_id ID of structure to provide.\n'''
+ u''' *\n'''
+ u''' * @return utils::SharedPtr of strucute\n'''
+ u''' */\n'''
+ u''' static '''
+ u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> '''
+ u'''ProvideObjectSchemaItemForStruct(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const StructIdentifiers::eType struct_id);\n'''
+ u'''\n'''
+ u''' /**\n'''
+ u''' * @brief Initializes all struct schemes.\n'''
+ u''' */\n'''
+ u''' void InitStructSchemes('''
+ u'''TStructsSchemaItems &struct_schema_items);\n'''
+ u'''\n'''
+ u''' /**\n'''
+ u''' * @brief Initializes all function schemes.\n'''
+ u''' *\n'''
+ u''' * @param struct_schema_items Struct schema items.\n'''
+ u''' * @param function_id_items Set of all elements '''
+ u'''of FunctionID enum.\n'''
+ u''' * @param message_type_items Set of all elements '''
+ u'''of messageType enum.\n'''
+ u''' */\n'''
+ u''' void InitFunctionSchemes(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const std::set<FunctionID::eType> &function_id_items,\n'''
+ u''' const std::set<messageType::eType> '''
+ u'''&message_type_items);\n'''
+ u'''\n'''
+ u'''$init_function_decls'''
+ u'''\n'''
+ u'''$init_struct_decls'''
+ u'''};''')
+
+ _function_return_comment = u''' * @return NsSmartDeviceLink::''' \
+ u'''NsSmartObjects::CSmartSchema\n'''
+
+ _function_decl_template = string.Template(
+ u'''$comment\n'''
+ u'''static NsSmartDeviceLink::NsSmartObjects::CSmartSchema '''
+ u'''InitFunction_${function_id}_${message_type}(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items,\n'''
+ u''' const std::set<FunctionID::eType> &function_id_items,\n'''
+ u''' const std::set<messageType::eType> &message_type_items);''')
+
+ _struct_decl_template = string.Template(
+ u'''$comment\n'''
+ u'''static '''
+ u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> '''
+ u'''InitStructSchemaItem_${struct_name}(\n'''
+ u''' const TStructsSchemaItems &struct_schema_items);''')
+
+ _class_comment_template = string.Template(
+ u'''/**\n'''
+ u''' * @brief Class $class_name.\n'''
+ u''' *\n'''
+ u''' * Params:\n'''
+ u'''$class_params'''
+ u''' */''')
+
+ _comment_doxygen_template = string.Template(
+ u'''/**\n'''
+ u'''$brief_description'''
+ u'''$description'''
+ u'''$design_description'''
+ u'''$issues'''
+ u'''$todos'''
+ u'''$returns */''')
+
+ _comment_cc_template = string.Template(
+ u'''$brief_description'''
+ u'''$description'''
+ u'''$design_description'''
+ u'''$issues'''
+ u'''$todos'''
+ u'''$returns''')
+
+ _enum_template = string.Template(
+ u'''namespace $name {\n'''
+ u'''$comment\n'''
+ u'''enum eType {\n'''
+ u'''$enum_items};\n'''
+ u'''} // $name\n''')
+
+ _enum_element_with_value_template = string.Template(
+ u'''$comment\n'''
+ u'''$name = $value''')
+
+ _enum_element_with_no_value_template = string.Template(
+ u'''$comment\n'''
+ u'''$name''')
+
+ _indent_template = u" "
diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py
new file mode 100755
index 0000000000..cf9887d39d
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py
@@ -0,0 +1,165 @@
+"""SmartFactory code generator for JSONRPC format.
+
+Defines JSONRPC format specific code generation rules.
+
+"""
+import string
+
+from generator.generators import SmartFactoryBase
+from generator import Model
+
+
+class CodeGenerator(SmartFactoryBase.CodeGenerator):
+
+ """JSONRPC SmartFactory generator.
+
+ Defines special cases that affects base code generation to make JSONRPC
+ format-friendly code.
+
+ """
+
+ def __init__(self):
+ """Construct new object."""
+
+ SmartFactoryBase.CodeGenerator.__init__(self)
+
+ def _gen_pre_function_schemas(self, functions):
+ """Generate specific code that goes before schema initialization.
+
+ JSON RPC generator generates code that adds specific schema for the
+ error_response and adds this schema for every available response.
+
+ Keyword arguments:
+ functions -- list of functions to generate code for.
+
+ Returns:
+ Source code with error_response schema initialization and adding to the
+ base SmartFactory..
+
+ """
+
+ code = u""
+ for function in functions:
+ if unicode(function.message_type.primary_name) == u"response":
+ code = u"".join(
+ [code, self._error_response_insert_template.substitute(
+ function_id=function.function_id.primary_name)])
+
+ if code:
+ return self._indent_code(
+ u"".join([self._error_response_schema_template, code]), 1)
+
+ return u""
+
+ def _preprocess_message_type(self, message_type):
+ """Preprocess message_type enum.
+
+ JSON RPC generator needs to add new message_type "error_response" in
+ case if at least one response available.
+
+ Keyword arguments:
+ message_type -- message_type enum to preprocess.
+
+ Returns:
+ Preprocessed message_type enum.
+
+ """
+
+ if "response" in message_type.elements:
+ message_type.elements[u"error_response"] = Model.EnumElement(
+ name=u"error_response")
+
+ return message_type
+
+ def _gen_schema_params_fill(self, message_type_name):
+ """Generate schema params fill code.
+
+ Provides constant set of params for the function in accordance to the
+ JSONRPC format.
+
+ Keyword arguments:
+ message_type_name -- Name of the messageType enum element.
+
+ Returns:
+ String with function schema params fill code.
+
+ """
+
+ return u"".join(
+ [self._base_params,
+ self._correlation_id_param
+ if unicode(message_type_name) != u"notification" else u"",
+ self._additional_response_params
+ if unicode(message_type_name) == u"response" else u""])
+
+ _error_response_insert_template = string.Template(
+ u'''functions_schemes_.insert(std::make_pair('''
+ u'''NsSmartDeviceLink::NsJSONHandler::'''
+ u'''SmartSchemaKey<FunctionID::eType, messageType::eType>('''
+ u'''FunctionID::${function_id}, messageType::error_response), '''
+ u'''error_response_schema));\n''')
+
+ _error_response_schema_template = (
+ u'''CObjectSchemaItem::Members '''
+ u'''params_members;\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember('''
+ u'''TEnumSchemaItem<FunctionID::eType>::create('''
+ u'''function_id_items), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember('''
+ u'''TEnumSchemaItem<messageType::eType>::create('''
+ u'''message_type_items), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember('''
+ u'''TNumberSchemaItem<int>::create(), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember('''
+ u'''TNumberSchemaItem<int>::create(), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember('''
+ u'''TNumberSchemaItem<int>::create(), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::kCode] = CObjectSchemaItem::SMember('''
+ u'''TNumberSchemaItem<int>::create(), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::kMessage] = CObjectSchemaItem::SMember('''
+ u'''CStringSchemaItem::create(), true);\n'''
+ u'''\n'''
+ u'''CObjectSchemaItem::Members root_members_map;\n'''
+ u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PARAMS] = CObjectSchemaItem::SMember('''
+ u'''CObjectSchemaItem::create(params_members), true);\n'''
+ u'''\n'''
+ u'''CSmartSchema error_response_schema('''
+ u'''CObjectSchemaItem::create(root_members_map));\n'''
+ u'''\n''')
+
+ _base_params = (
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::'''
+ u'''SMember(TEnumSchemaItem<FunctionID::eType>::'''
+ u'''create(function_id_items), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::'''
+ u'''SMember(TEnumSchemaItem<messageType::eType>::'''
+ u'''create(message_type_items), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::'''
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::'''
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+ )
+
+ _correlation_id_param = (
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::'''
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+ )
+
+ _additional_response_params = (
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::'''
+ u'''strings::kCode] = CObjectSchemaItem::'''
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+ )
diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py b/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py
new file mode 100755
index 0000000000..b3fb61f4a9
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py
@@ -0,0 +1,92 @@
+"""SmartFactory code generator for SDLRPC format.
+
+Defines SDLRPC format specific code generation rules.
+
+"""
+from generator.generators import SmartFactoryBase
+
+
+class CodeGenerator(SmartFactoryBase.CodeGenerator):
+
+ """SDLRPC SmartFactory generator.
+
+ Defines special cases that affects base code generation to make SDLRPC
+ format-friendly code.
+
+ """
+
+ def __init__(self):
+ """Construct new object."""
+
+ SmartFactoryBase.CodeGenerator.__init__(self)
+
+ def _gen_pre_function_schemas(self, functions):
+ """Generate specific code that goes before schema initialization.
+
+ In SDL RPC generator there is no need to generate any code before
+ schemas initialization.
+
+ Keyword arguments:
+ functions -- list of functions to generate code for.
+
+ Returns:
+ Empty string.
+
+ """
+
+ return u""
+
+ def _preprocess_message_type(self, message_type):
+ """Preprocess message_type enum.
+
+ In SDL RPC generator there is no need to preprocess message_type
+ enum values.
+
+ Keyword arguments:
+ message_type -- message_type enum to preprocess.
+
+ Returns:
+ Initial message_type enum without any modifications.
+
+ """
+
+ return message_type
+
+ def _gen_schema_params_fill(self, message_type_name):
+ """Generate schema params fill code.
+
+ Provides constant set of params for the function in accordance to the
+ SDLRPC format (both v1 and v2).
+
+ Keyword arguments:
+ message_type_name -- Name of the messageType enum element.
+
+ Returns:
+ String with function schema params fill code.
+
+ """
+
+ base_params = \
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \
+ u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::''' \
+ u'''SMember(TEnumSchemaItem<FunctionID::eType>::''' \
+ u'''create(function_id_items), true);\n''' \
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \
+ u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::''' \
+ u'''SMember(TEnumSchemaItem<messageType::eType>::''' \
+ u'''create(message_type_items), true);\n''' \
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \
+ u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::''' \
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' \
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \
+ u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::''' \
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+
+ correlation_id_param = \
+ u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \
+ u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::''' \
+ u'''SMember(TNumberSchemaItem<int>::create(), true);\n'''
+
+ return u"".join([base_params, correlation_id_param
+ if unicode(message_type_name) !=
+ u"notification" else u""])
diff --git a/tools/InterfaceGenerator/generator/generators/__init__.py b/tools/InterfaceGenerator/generator/generators/__init__.py
new file mode 100755
index 0000000000..57e528dc8d
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/generators/__init__.py
@@ -0,0 +1,3 @@
+"""Package that contains generators from internal model representation to
+different formats.
+"""
diff --git a/tools/InterfaceGenerator/generator/parsers/JSONRPC.py b/tools/InterfaceGenerator/generator/parsers/JSONRPC.py
new file mode 100755
index 0000000000..092f41ec17
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/parsers/JSONRPC.py
@@ -0,0 +1,89 @@
+"""JSON RPC parser.
+
+Contains parser for JSON RPC XML format.
+
+"""
+
+from generator.parsers import RPCBase
+
+
+class Parser(RPCBase.Parser):
+
+ """JSON RPC parser."""
+
+ def __init__(self):
+ """Constructor."""
+ super(Parser, self).__init__()
+ self._interface_name = None
+
+ def _parse_root(self, root):
+ """Parse root XML element.
+
+ This implementation parses root as interfaces element with multiple
+ interfaces in it.
+
+ Keyword arguments:
+ root -- root element.
+
+ """
+
+ self._params = root.attrib
+ self._interface_name = None
+
+ for element in root:
+ if element.tag != "interface":
+ raise RPCBase.ParseError("Subelement '" + element.tag +
+ "' is unexpected in interfaces")
+
+ if "name" not in element.attrib:
+ raise RPCBase.ParseError(
+ "Name is not specified for interface")
+
+ self._interface_name = element.attrib["name"]
+ self._parse_interface(element, self._interface_name + "_")
+
+ def _provide_enum_element_for_function(self, enum_name, element_name):
+ """Provide enum element for functions.
+
+ This implementation replaces the underscore separating interface and
+ function name with dot and sets it as name of enum element leaving
+ the name with underscore as internal_name. For enums other than
+ FunctionID the base implementation is called.
+
+ Returns EnumElement.
+
+ """
+
+ name = element_name
+ internal_name = None
+
+ if "FunctionID" == enum_name:
+ prefix_length = len(self._interface_name) + 1
+ if element_name[:prefix_length] != self._interface_name + '_':
+ raise RPCBase.ParseError(
+ "Unexpected prefix for function id '" +
+ element_name + "'")
+ name = self._interface_name + "." + element_name[prefix_length:]
+ internal_name = element_name
+
+ element = super(Parser, self)._provide_enum_element_for_function(
+ enum_name,
+ name)
+
+ if internal_name is not None:
+ element.internal_name = internal_name
+
+ return element
+
+ def _check_function_param_name(self, function_param_name):
+ """Check function param name.
+
+ This method is called to check whether the newly parsed function
+ parameter name conflicts with some predefined name.
+ """
+
+ if function_param_name in ['method', 'code']:
+ raise RPCBase.ParseError(
+ "'" + function_param_name +
+ "' is a predefined name and can't be used" +
+ " as a function parameter name")
diff --git a/tools/InterfaceGenerator/generator/parsers/RPCBase.py b/tools/InterfaceGenerator/generator/parsers/RPCBase.py
new file mode 100755
index 0000000000..2b3db62d56
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/parsers/RPCBase.py
@@ -0,0 +1,758 @@
+"""RPC XML base parser.
+
+Contains base parser for SDLRPC v1/v2 and JSON RPC XML format.
+
+"""
+
+import collections
+import xml.etree.ElementTree
+
+from generator import Model
+
+
+class ParseError(Exception):
+
+ """Parse error.
+
+ This exception is raised when XML contains errors and can't be parsed.
+
+ """
+
+ pass
+
+
+class Parser(object):
+
+ """RPC XML Parser base.
+
+ This class must not be used directly. One of its subclasses must be used
+ instead.
+
+ """
+
+ def __init__(self):
+ """Constructor."""
+ self._types = {}
+ self._enums = collections.OrderedDict()
+ self._structs = collections.OrderedDict()
+ self._functions = collections.OrderedDict()
+ self._params = {}
+
+ def parse(self, filename):
+ """Parse XML.
+
+ Returns an instance of generator.Model.Interface containing parsed
+ interface or raises ParseError if input XML contains errors
+ and can't be parsed.
+
+ Keyword arguments:
+ filename -- name of input XML file.
+
+ """
+
+ tree = xml.etree.ElementTree.parse(filename)
+ root = tree.getroot()
+
+ self._enums = self._initialize_enums()
+ self._structs = collections.OrderedDict()
+ self._functions = collections.OrderedDict()
+ self._params = {}
+
+ self._types = dict(self._enums.items())
+
+ self._parse_root(root)
+
+ return Model.Interface(enums=self._enums, structs=self._structs,
+ functions=self._functions, params=self._params)
+
+ def _initialize_enums(self):
+ """Initialize enums.
+
+ The default implementation returns an OrderedDict with two empty
+ enums: "FunctionID" and "messageType". Required for formats where
+ these enums must be generated automatically according to the declared
+ in the XML functions.
+
+ These enums are filled during the parsing of the functions.
+
+ """
+ return collections.OrderedDict(
+ [("FunctionID", Model.Enum(name="FunctionID")),
+ ("messageType", Model.Enum(name="messageType"))])
+
+ def _check_enum_name(self, enum):
+ """Check enum name.
+
+ This method is called to check whether the newly parsed enum's name
+ conflicts with some predefined enum.
+
+ This implementation raises an error if enum name is one of the
+ predefined enums "FunctionID" or "messageType" which must not be
+ declared explicitly in the XML.
+
+ """
+ if enum.name in ["FunctionID", "messageType"]:
+ raise ParseError(
+ "Enum '" + enum.name +
+ "' is generated automatically in SDLRPCV1 and"
+ " must not be declared in xml file")
+
+ def _check_function_param_name(self, function_param_name):
+ """Check function param name.
+
+ This method is called to check whether the newly parsed function
+ parameter name conflicts with some predefined name.
+
+ This implementation doesn't check anything because there is no
+ predefined names in base RPC XML.
+ """
+
+ pass
+
+ def _parse_root(self, root):
+ """Parse root XML element.
+
+ Default implementation parses root as interface element without a
+ prefix.
+
+ Keyword arguments:
+ root -- root element.
+
+ """
+
+ self._parse_interface(root, "")
+
+ def _parse_interface(self, interface, prefix):
+ """Parse interface element.
+
+ Keyword arguments:
+ interface -- interface element.
+ prefix -- string prefix for all types of the interface.
+
+ """
+ if interface.tag != "interface":
+ raise ParseError("Invalid interface tag: " + interface.tag)
+
+ params, subelements, attrib = self._parse_base_item(interface, "")
+
+ for param in ["description", "design_description", "todos"]:
+ if 0 != len(params[param]):
+ attrib[param] = "\n".join(params[param])
+
+ if 0 != len(params["issues"]):
+ attrib["issues"] = "\n".join(i.value for i in params["issues"])
+
+ self._params = dict(
+ self._params.items() +
+ [(prefix + p[0], p[1]) for p in attrib.items()])
+
+ for element in subelements:
+ if element.tag == "enum":
+ enum = self._parse_enum(element, prefix)
+ self._check_enum_name(enum)
+ self._add_item(self._enums, enum)
+ self._add_type(enum)
+ elif element.tag == "struct":
+ struct = self._parse_struct(element, prefix)
+ self._add_item(self._structs, struct)
+ self._add_type(struct)
+ elif element.tag == "function":
+ function = self._parse_function(element, prefix)
+ self._add_item(self._functions, function,
+ (function.function_id, function.message_type))
+ else:
+ raise ParseError("Unexpected element: " + element.tag)
+
+ @staticmethod
+ def _add_item(items, item, key=None):
+ """Add new item in the items dictionary with given key.
+
+ Performs additional check for presence in the dictionary and throws
+ ParseError exception if key already exist.
+
+ """
+ if key is None:
+ key = item.name
+
+ if key in items:
+ raise ParseError(type(item).__name__ + " '" + str(key) +
+ "' is declared more than once")
+ items[key] = item
+
+ def _add_type(self, _type):
+ """Add new type in the internal types dictionary.
+
+ Performs additional check for presence type with same name in the
+ dictionary and throws ParseError exception if key already exist.
+
+ """
+ if _type.name in self._types:
+ raise ParseError("Type '" + _type.name +
+ "' is declared as both struct and enum")
+
+ self._types[_type.name] = _type
+
+ def _parse_enum(self, element, prefix):
+ """Parse element as enumeration.
+
+ Returns an instance of generator.Model.Enum
+
+ """
+ params, subelements, attributes = \
+ self._parse_base_item(element, prefix)
+
+ internal_scope = None
+ scope = None
+ for attribute in attributes:
+ if attribute == "internal_scope":
+ internal_scope = attributes[attribute]
+ elif attribute == "scope":
+ scope = attributes[attribute]
+ else:
+ raise ParseError("Unexpected attribute '" + attribute +
+ "' in enum '" + params["name"] + "'")
+ params["internal_scope"] = internal_scope
+ params["scope"] = scope
+
+ elements = collections.OrderedDict()
+ for subelement in subelements:
+ if subelement.tag == "element":
+ self._add_item(elements, self._parse_enum_element(subelement))
+ else:
+ raise ParseError("Unexpected element '" + subelement.tag +
+ "' in enum '" + params["name"] + "'")
+ params["elements"] = elements
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.Enum(**params)
+
+ def _parse_struct(self, element, prefix):
+ """Parse element as structure.
+
+ Returns an instance of generator.Model.Struct
+
+ """
+ params, subelements, attrib = self._parse_base_item(element, prefix)
+
+ scope = None
+ for attribute in attrib:
+ if attribute == "scope":
+ scope = attrib[attribute]
+ else:
+ raise ParseError("Unexpected attribute '" + attribute +
+ "' in struct '" + params["name"] + "'")
+ params["scope"] = scope
+
+ members = collections.OrderedDict()
+ for subelement in subelements:
+ if subelement.tag == "param":
+ self._add_item(members, self._parse_param(subelement, prefix))
+ else:
+ raise ParseError("Unexpected subelement '" + subelement.name +
+ "' in struct '" + params["name"] + "'")
+ params["members"] = members
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.Struct(**params)
+
+ def _parse_function(self, element, prefix):
+ """Parse element as function.
+
+ Returns an instance of generator.Model.Function
+
+ """
+ params, subelements, attributes = \
+ self._parse_base_item(element, prefix)
+
+ function_id, message_type = self._parse_function_id_type(
+ params["name"],
+ attributes)
+
+ scope = None
+ for attribute in attributes:
+ if attribute == "scope":
+ scope = attributes[attribute]
+
+ params["function_id"] = function_id
+ params["message_type"] = message_type
+ params["scope"] = scope
+
+ function_params = collections.OrderedDict()
+ for subelement in subelements:
+ if subelement.tag == "param":
+ function_param = self._parse_function_param(subelement,
+ prefix)
+ self._check_function_param_name(function_param.name)
+ if function_param.name in function_params:
+ raise ParseError("Parameter '" + function_param.name +
+ "' is specified more than once" +
+ " for function '" + params["name"] + "'")
+ function_params[function_param.name] = function_param
+ else:
+ raise ParseError("Unexpected subelement '" + subelement.tag +
+ "' in function '" + params["name"] + "'")
+ params["params"] = function_params
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.Function(**params)
+
+ def _parse_function_id_type(self, function_name, attrib):
+ """Parse function id and message type according to XML format.
+
+ This implementation takes function name as function id and extracts
+ attribute "messagetype" as message type and searches them in enums
+ "FunctionID" and "messageType" adding the missing elements if
+ necessary.
+
+ Returns function id and message type as an instances of EnumElement.
+
+ """
+ if "messagetype" not in attrib:
+ raise ParseError("No messagetype specified for function '" +
+ function_name + "'")
+
+ function_id = self._provide_enum_element_for_function(
+ "FunctionID",
+ function_name)
+
+ message_type = self._provide_enum_element_for_function(
+ "messageType",
+ self._extract_attrib(attrib, "messagetype"))
+
+ return function_id, message_type
+
+ def _provide_enum_element_for_function(self, enum_name, element_name):
+ """Provide enum element for functions.
+
+ Search an element in an enum and add it if it is missing.
+
+ Returns EnumElement.
+
+ """
+ if enum_name not in self._types:
+ raise ParseError("Enum '" + enum_name +
+ "' is not initialized")
+
+ enum = self._types[enum_name]
+
+ if not isinstance(enum, Model.Enum):
+ raise ParseError("'" + enum_name + "' is not an enum")
+
+ if element_name not in enum.elements:
+ enum.elements[element_name] = Model.EnumElement(name=element_name)
+
+ return enum.elements[element_name]
+
+ def _parse_base_item(self, element, prefix):
+ """Parse element as base item.
+
+ Returns an params, sub-elements and attributes of the element
+
+ """
+ params = {}
+
+ description = []
+ design_description = []
+ issues = []
+ todos = []
+ subelements = []
+
+ if "name" not in element.attrib:
+ raise ParseError("Name is not specified for " + element.tag)
+
+ params["name"] = prefix + element.attrib["name"]
+ attrib = dict(element.attrib.items())
+ del attrib["name"]
+
+ params["platform"] = self._extract_attrib(attrib, "platform")
+
+ for subelement in element:
+ if subelement.tag == "description":
+ description.append(self._parse_simple_element(subelement))
+ elif subelement.tag == "designdescription":
+ design_description.append(
+ self._parse_simple_element(subelement))
+ elif subelement.tag == "todo":
+ todos.append(self._parse_simple_element(subelement))
+ elif subelement.tag == "issue":
+ issues.append(self._parse_issue(subelement))
+ else:
+ subelements.append(subelement)
+
+ params["description"] = description
+ params["design_description"] = design_description
+ params["issues"] = issues
+ params["todos"] = todos
+
+ return params, subelements, attrib
+
+ @staticmethod
+ def _parse_simple_element(element):
+ """Parse element as simple element and returns it's text.
+
+ Element is simple when it contains no subelements and attributes.
+
+ Returns element text if present or empty string if not
+
+ """
+ if len(element) != 0:
+ raise ParseError("Unexpected subelements in '" +
+ element.tag + "'")
+ if len(element.attrib) != 0:
+ raise ParseError("Unexpected attributes in '" +
+ element.tag + "'")
+ return element.text if element.text is not None else ""
+
+ @staticmethod
+ def _parse_issue(element):
+ """Parse element as issue.
+
+ Issue must not contain subelements and attributes.
+
+ Returns an instance of generator.Model.Issue
+
+ """
+ if len(element) != 0:
+ raise ParseError("Unexpected subelements in issue")
+ if "creator" not in element.attrib:
+ raise ParseError("No creator in issue")
+ if len(element.attrib) != 1:
+ raise ParseError("Unexpected attributes in issue")
+
+ return Model.Issue(
+ creator=element.attrib["creator"],
+ value=element.text if element.text is not None else "")
+
+ def _parse_enum_element(self, element):
+ """Parse element as element of enumeration.
+
+ Returns an instance of generator.Model.EnumElement
+
+ """
+ params, subelements, attributes = self._parse_base_item(element, "")
+
+ if len(subelements) != 0:
+ raise ParseError("Unexpected subelements in enum element")
+
+ self._ignore_attribute(attributes, "hexvalue")
+ self._ignore_attribute(attributes, "scope")
+ self._ignore_attribute(attributes, "rootscreen")
+
+ internal_name = None
+ value = None
+ for attribute in attributes:
+ if attribute == "internal_name":
+ internal_name = attributes[attribute]
+ elif attribute == "value":
+ try:
+ value = int(attributes[attribute])
+ except:
+ raise ParseError("Invalid value for enum element: '" +
+ attributes[attribute] + "'")
+ params["internal_name"] = internal_name
+ params["value"] = value
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.EnumElement(**params)
+
+ def _parse_param(self, element, prefix):
+ """Parse element as structure parameter.
+
+ Returns an instance of generator.Model.Param
+
+ """
+ params, subelements, attrib = \
+ self._parse_param_base_item(element, prefix)
+
+ if len(attrib) != 0:
+ raise ParseError("""Unknown attribute(s) {0} in param {1}
+ """.format(attrib, params["name"]))
+
+ if len(subelements) != 0:
+ raise ParseError("Unknown subelements in param '" +
+ params["name"] + "'")
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.Param(**params)
+
+ def _parse_function_param(self, element, prefix):
+ """Parse element as function parameter.
+
+ Returns an instance of generator.Model.FunctionParam
+
+ """
+ params, subelements, attrib = \
+ self._parse_param_base_item(element, prefix)
+
+ default_value = None
+ default_value_string = self._extract_attrib(attrib, "defvalue")
+ if default_value_string is not None:
+ param_type = params["param_type"]
+ if type(param_type) is Model.Boolean:
+ default_value = \
+ self._get_bool_from_string(default_value_string)
+ elif type(param_type) is Model.Integer:
+ try:
+ default_value = int(default_value_string)
+ except:
+ raise ParseError("Invalid value for integer: '" +
+ default_value_string + "'")
+ elif type(param_type) is Model.Double:
+ try:
+ default_value = float(default_value_string)
+ except:
+ raise ParseError("Invalid value for float: '" +
+ default_value_string + "'")
+ elif type(param_type) is Model.String:
+ default_value = default_value_string
+ elif type(param_type) is Model.Enum or \
+ type(param_type) is Model.EnumSubset:
+ if type(param_type) is Model.EnumSubset:
+ allowed_elements = param_type.allowed_elements
+ else:
+ allowed_elements = param_type.elements
+ if default_value_string not in allowed_elements:
+ raise ParseError("Default value '" + default_value_string +
+ "' for parameter '" + params["name"] +
+ "' is not a member of " +
+ type(param_type).__name__ +
+ "'" + params["name"] + "'")
+ default_value = allowed_elements[default_value_string]
+ else:
+ raise ParseError("Default value specified for " +
+ type(param_type).__name__)
+ params["default_value"] = default_value
+
+ if len(attrib) != 0:
+ raise ParseError("Unexpected attributes in parameter '" +
+ params["name"] + "'")
+
+ if len(subelements) != 0:
+ raise ParseError("Unexpected subelements in parameter '" +
+ params["name"] + "'")
+
+ # Magic usage is correct
+ # pylint: disable=W0142
+ return Model.FunctionParam(**params)
+
+ def _parse_param_base_item(self, element, prefix):
+ """Parse base param items.
+
+ Returns params, other subelements and attributes.
+
+ """
+ params, subelements, attrib = self._parse_base_item(element, "")
+
+ params["is_mandatory"] = self._extract_optional_bool_attrib(
+ attrib, "mandatory", True)
+
+ scope = self._extract_attrib(attrib, "scope")
+ if scope is not None:
+ params["scope"] = scope
+
+ default_value = None;
+ param_type = None
+ type_name = self._extract_attrib(attrib, "type")
+ if type_name is None:
+ raise ParseError("Type is not specified for parameter '" +
+ params["name"] + "'")
+ if type_name == "Boolean":
+ default_value = self._extract_attrib(
+ attrib, "defvalue")
+ if default_value != None:
+ default_value = self._get_bool_from_string(default_value);
+ param_type = Model.Boolean(default_value=default_value)
+ elif type_name == "Integer" or \
+ type_name == "Float":
+ min_value = self._extract_optional_number_attrib(
+ attrib, "minvalue", int if type_name == "Integer" else float)
+ max_value = self._extract_optional_number_attrib(
+ attrib, "maxvalue", int if type_name == "Integer" else float)
+ default_value = self._extract_optional_number_attrib(
+ attrib, "defvalue", int if type_name == "Integer" else float)
+
+ param_type = \
+ (Model.Integer if type_name == "Integer" else Model.Double)(
+ min_value=min_value,
+ max_value=max_value,
+ default_value=default_value)
+ elif type_name == "String":
+ min_length = self._extract_optional_number_attrib(
+ attrib, "minlength")
+ # if minlength is not defined default value is 1
+ if min_length is None:
+ min_length = 1
+ max_length = self._extract_optional_number_attrib(
+ attrib, "maxlength")
+ default_value = self._extract_attrib(attrib, "defvalue")
+ param_type = Model.String(min_length=min_length, max_length=max_length, default_value=default_value)
+ else:
+ if 1 == type_name.count("."):
+ custom_type_name = type_name.replace(".", "_")
+ else:
+ custom_type_name = prefix + type_name
+
+ if custom_type_name in self._types:
+ param_type = self._types[custom_type_name]
+ default_value = self._extract_attrib(attrib, "defvalue")
+ if default_value != None:
+ if default_value not in param_type.elements:
+ raise ParseError("Default value '" + default_value +
+ "' for parameter '" + params["name"] +
+ "' is not a member of " +
+ type(param_type).__name__ +
+ "'" + params["name"] + "'")
+ default_value = param_type.elements[default_value]
+ else:
+ raise ParseError("Unknown type '" + type_name + "'")
+
+ if self._extract_optional_bool_attrib(attrib, "array", False):
+ min_size = self._extract_optional_number_attrib(attrib,
+ "minsize")
+ max_size = self._extract_optional_number_attrib(attrib,
+ "maxsize")
+ param_type = Model.Array(element_type=param_type,
+ min_size=min_size,
+ max_size=max_size)
+
+ base_type = \
+ param_type.element_type if isinstance(param_type, Model.Array) \
+ else param_type
+
+ other_subelements = []
+ for subelement in subelements:
+ if subelement.tag == "element":
+ if type(base_type) is not Model.Enum and \
+ type(base_type) is not Model.EnumSubset:
+ raise ParseError("Elements specified for parameter '" +
+ params["name"] + "' of type " +
+ type(base_type).__name__)
+ if type(base_type) is Model.Enum:
+ base_type = Model.EnumSubset(
+ name=params["name"],
+ enum=base_type,
+ description=params["description"],
+ design_description=params["design_description"],
+ issues=params["issues"],
+ todos=params["todos"],
+ allowed_elements={})
+ if "name" not in subelement.attrib:
+ raise ParseError(
+ "Element name is not specified for parameter '" +
+ params["name"] + "'")
+ element_name = subelement.attrib["name"]
+ if len(subelement.attrib) != 1:
+ raise ParseError("Unexpected attributes for element '" +
+ element_name + "' of parameter '" +
+ params["name"])
+ if len(subelement.getchildren()) != 0:
+ raise ParseError("Unexpected subelements for element '" +
+ element_name + "' of parameter '" +
+ params["name"])
+ if element_name in base_type.allowed_elements:
+ raise ParseError("Element '" + element_name +
+ "' is specified more than once for" +
+ " parameter '" + params["name"] + "'")
+ if element_name not in base_type.enum.elements:
+ raise ParseError("Element '" + element_name +
+ "' is not a member of enum '" +
+ base_type.enum.name + "'")
+ base_type.allowed_elements[element_name] = \
+ base_type.enum.elements[element_name]
+ else:
+ other_subelements.append(subelement)
+
+ if isinstance(param_type, Model.Array):
+ param_type.element_type = base_type
+ else:
+ param_type = base_type
+
+ params["param_type"] = param_type
+ if default_value is not None:
+ params["default_value"] = default_value
+
+ return params, other_subelements, attrib
+
+ def _extract_optional_bool_attrib(self, attrib, name, default):
+ """Extract boolean attribute with given name.
+
+ Returns value of the attribute.
+
+ """
+ value = self._extract_attrib(attrib, name)
+
+ if value is None:
+ value = default
+ else:
+ value = self._get_bool_from_string(value)
+
+ return value
+
+ def _extract_optional_number_attrib(self, attrib, name, _type=int):
+ """Extract number attribute with given name.
+
+ Returns value of the attribute.
+
+ """
+ value = self._extract_attrib(attrib, name)
+
+ if value is not None:
+ try:
+ value = _type(value)
+ except:
+ raise ParseError("Invlaid value for " + _type.__name__ +
+ ": '" + value + "'")
+
+ return value
+
+ @staticmethod
+ def _extract_attrib(attrib, name):
+ """Extract attribute with given name.
+
+ Returns value of the attribute.
+
+ """
+ value = None
+
+ if name in attrib:
+ value = attrib[name]
+ del attrib[name]
+
+ return value
+
+ @staticmethod
+ def _get_bool_from_string(bool_string):
+ """Convert string representation of boolean to real bool value.
+
+ Returns converted value.
+
+ """
+ value = None
+
+ if bool_string in ['0', 'false']:
+ value = False
+ elif bool_string in ['1', 'true']:
+ value = True
+ else:
+ raise ParseError("Invalid value for bool: '" +
+ bool_string + "'")
+
+ return value
+
+ def _ignore_attribute(self, attrib, name):
+ """To be called when attribute is meaningless in terms
+ of code generation but it's presence is not issue.
+
+ Removes this attribute from attribute list.
+
+ """
+ if name in attrib:
+ del attrib[name]
+ print ("Ignoring attribute '" +
+ name + "'")
+ return True
diff --git a/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py b/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py
new file mode 100755
index 0000000000..52158ee93b
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py
@@ -0,0 +1,14 @@
+"""SDLRPCV1 parser.
+
+Contains parser for SDLRPCV1 XML format.
+
+"""
+
+from generator.parsers import RPCBase
+
+
+class Parser(RPCBase.Parser):
+
+ """SDLRPCV1 parser."""
+
+ pass
diff --git a/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py b/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py
new file mode 100755
index 0000000000..3d67c6e4c6
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py
@@ -0,0 +1,88 @@
+"""SDLRPCV2 parser.
+
+Contains parser for SDLRPCV2 XML format.
+
+"""
+
+import collections
+
+from generator import Model
+from generator.parsers import RPCBase
+
+
+class Parser(RPCBase.Parser):
+
+ """SDLRPCV2 parser."""
+
+ def _initialize_enums(self):
+ """Initialize enums.
+
+ This implementation returns empty OrderedDict because in SDLRPCV2
+ all enums must be declared explicitly in the XML file.
+
+ """
+ return collections.OrderedDict()
+
+ def _check_enum_name(self, enum):
+ """Check enum name.
+
+ This method is called to check whether the newly parsed enum's name
+ conflicts with some predefined enum.
+ As SDLRPCV2 has no predefined enums this implementation does nothing.
+
+ """
+ pass
+
+ def _parse_function_id_type(self, function_name, attrib):
+ """Parse function id and message type according to XML format.
+
+ This implementation extracts attribute "FunctionID" as function id
+ and messagetype as message type and searches them in enums
+ "FunctionID" and "messageType". If at least one of them (or the entire
+ enum) is missing it raises an error.
+
+ Returns function id and message type as an instances of EnumElement.
+
+ """
+ if "functionID" not in attrib:
+ raise RPCBase.ParseError(
+ "No functionID specified for function '" +
+ function_name + "'")
+
+ if "messagetype" not in attrib:
+ raise RPCBase.ParseError(
+ "No messagetype specified for function '" +
+ function_name + "'")
+
+ function_id = self._get_enum_element_for_function(
+ "FunctionID",
+ self._extract_attrib(attrib, "functionID"))
+ message_type = self._get_enum_element_for_function(
+ "messageType",
+ self._extract_attrib(attrib, "messagetype"))
+
+ return function_id, message_type
+
+ def _get_enum_element_for_function(self, enum_name, element_name):
+ """Get enum element with given name from given enumeration.
+
+ Returns an instance of generator.Model.EnumElement.
+
+ """
+ if enum_name not in self._types:
+ raise RPCBase.ParseError(
+ "Enumeration '" + enum_name +
+ "' must be declared before any function")
+
+ enum = self._types[enum_name]
+
+ if type(enum) is not Model.Enum:
+ raise RPCBase.ParseError("'" + enum_name +
+ "' is not an enumeration")
+
+ if element_name not in enum.elements:
+ raise RPCBase.ParseError(
+ "'" + element_name +
+ "' is not a member of enum '" + enum_name + "'")
+
+ return enum.elements[element_name]
diff --git a/tools/InterfaceGenerator/generator/parsers/__init__.py b/tools/InterfaceGenerator/generator/parsers/__init__.py
new file mode 100755
index 0000000000..7005503b0c
--- /dev/null
+++ b/tools/InterfaceGenerator/generator/parsers/__init__.py
@@ -0,0 +1,3 @@
+"""Package that contains parsers from different formats to internal model
+representation.
+"""