Exemplo n.º 1
0
    def expand_attributes(self, attributes):
        for i in range(0, len(attributes)):
            [attrib_name,
             had_hyphen] = strFunctions.remove_hyphens(attributes[i]['name'])
            capname = strFunctions.upper_first(attrib_name)
            if had_hyphen:
                orig_name = attributes[i]['name']
                attributes[i]['name'] = strFunctions.lower_first(orig_name)
            else:
                attributes[i]['name'] = strFunctions.lower_first(capname)
            attributes[i]['capAttName'] = capname
            attributes[i]['memberName'] = 'm' + capname
            attributes[i]['pluralName'] = \
                strFunctions.plural(attrib_name)
            attributes[i]['isEnum'] = False
            attributes[i]['isArray'] = False
            attributes[i]['isVector'] = False
            attributes[i]['children_overwrite'] = False
            att_type = attributes[i]['type']
            if att_type == 'SId' or att_type == 'SIdRef' or att_type == 'IDREF' or att_type == 'ID':
                attributes[i]['attType'] = 'string'
                attributes[i]['attTypeCode'] = 'std::string&'
                attributes[i]['CType'] = 'const char *'
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = '""'
            elif att_type == 'UnitSId' or att_type == 'UnitSIdRef':
                attributes[i]['attType'] = 'string'
                attributes[i]['attTypeCode'] = 'std::string&'
                attributes[i]['CType'] = 'const char *'
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = '""'
            elif att_type == 'string':
                attributes[i]['attType'] = 'string'
                attributes[i]['attTypeCode'] = 'std::string&'
                attributes[i]['CType'] = 'const char *'
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = '""'
            elif att_type == 'double':
                attributes[i]['attType'] = 'double'
                attributes[i]['attTypeCode'] = 'double'
                attributes[i]['CType'] = 'double'
                attributes[i]['isNumber'] = True
                attributes[i]['default'] = 'util_NaN()'
            elif att_type == 'int':
                attributes[i]['attType'] = 'integer'
                attributes[i]['attTypeCode'] = 'int'
                attributes[i]['CType'] = 'int'
                attributes[i]['isNumber'] = True
                attributes[i]['default'] = '{0}_INT_' \
                                           'MAX'.format(self.cap_language)
            elif att_type == 'uint':
                attributes[i]['attType'] = 'unsigned integer'
                attributes[i]['attTypeCode'] = 'unsigned int'
                attributes[i]['CType'] = 'unsigned int'
                attributes[i]['isNumber'] = True
                attributes[i]['default'] = '{0}_INT_' \
                                           'MAX'.format(self.cap_language)
            elif att_type == 'bool' or att_type == 'boolean':
                attributes[i]['attType'] = 'boolean'
                attributes[i]['attTypeCode'] = 'bool'
                attributes[i]['CType'] = 'int'
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'false'
            elif att_type == 'enum':
                attributes[i]['isEnum'] = True
                attributes[i]['attType'] = 'enum'
                attributes[i]['attTypeCode'] = attributes[i]['element'] + '_t'
                attributes[i]['CType'] = attributes[i]['element'] + '_t'
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = \
                    query.get_default_enum_value(attributes[i])
            elif att_type == 'element':
                el_name = attributes[i]['element']
                at_name = attrib_name
                attributes[i]['attType'] = 'element'
                if attrib_name == 'math':
                    if global_variables.is_package:
                        attributes[i]['attTypeCode'] = 'ASTNode*'
                        attributes[i]['CType'] = 'ASTNode_t*'
                    else:
                        attributes[i][
                            'attTypeCode'] = 'LIBSBML_CPP_NAMESPACE_QUALIFIER ASTNode*'
                        attributes[i][
                            'CType'] = 'LIBSBML_CPP_NAMESPACE_QUALIFIER ASTNode_t*'
                else:
                    attributes[i][
                        'attTypeCode'] = attributes[i]['element'] + '*'
                    attributes[i]['CType'] = attributes[i]['element'] + '_t*'
                if attributes[i][
                        'attTypeCode'] == 'XMLNode*' and not global_variables.is_package:
                    attributes[i][
                        'attTypeCode'] = 'LIBSBML_CPP_NAMESPACE_QUALIFIER {0}*'.format(
                            attributes[i]['element'])
                    attributes[i][
                        'CType'] = 'LIBSBML_CPP_NAMESPACE_QUALIFIER {0}_t*'.format(
                            attributes[i]['element'])

                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'NULL'
                if strFunctions.compare_no_case(
                        strFunctions.remove_prefix(el_name), at_name):
                    attributes[i]['children_overwrite'] = False
                else:
                    attributes[i]['children_overwrite'] = True
            elif att_type == 'lo_element' or att_type == 'inline_lo_element':
                childclass = query.get_class(attributes[i]['element'],
                                             attributes[i]['root'])
                if 'lo_class_name' in childclass and childclass[
                        'lo_class_name'] != '':
                    name = childclass['lo_class_name']
                else:
                    name = strFunctions.list_of_name(attributes[i]['element'])
                plural = strFunctions.plural_no_prefix(
                    attributes[i]['element'])

                attributes[i]['attType'] = 'lo_element'
                attributes[i]['attTypeCode'] = name
                attributes[i]['CType'] = 'ListOf_t'
                attributes[i]['memberName'] = 'm' + plural
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'NULL'
                if 'xml_name' in attributes[
                        i] and attributes[i]['xml_name'] != '':
                    attributes[i]['used_child_name'] = strFunctions.singular(
                        attributes[i]['xml_name'])
            elif att_type == 'array':
                attributes[i]['isArray'] = True
                if attributes[i]['element'] == 'Integer' or attributes[i][
                        'element'] == 'integer':
                    attributes[i]['element'] = 'int'
                else:
                    attributes[i]['element'] = \
                        strFunctions.lower_first(attributes[i]['element'])
                attributes[i]['attType'] = 'array'
                attributes[i]['attTypeCode'] = attributes[i]['element'] + '*'
                attributes[i]['CType'] = attributes[i]['attTypeCode']
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'NULL'
            elif att_type == 'vector':
                attributes[i]['isVector'] = True
                if attributes[i]['element'] == 'Integer' or attributes[i][
                        'element'] == 'integer':
                    attributes[i]['element'] = 'int'
                else:
                    attributes[i]['element'] = \
                        strFunctions.lower_first(attributes[i]['element'])
                attributes[i]['attType'] = 'vector'
                attributes[i]['attTypeCode'] = 'std::vector<{0}>'.format(
                    attributes[i]['element'])
                attributes[i]['CType'] = attributes[i]['attTypeCode']
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'NULL'
            else:
                global_variables.code_returned \
                    = global_variables.return_codes['unknown type used']
                attributes[i]['attType'] = 'FIXME_{0}'.format(att_type)
                attributes[i]['attTypeCode'] = 'FIXME_{0}'.format(att_type)
                attributes[i]['CType'] = 'FIXME_{0}'.format(att_type)
                attributes[i]['isNumber'] = False
                attributes[i]['default'] = 'FIXME_{0}'.format(att_type)
        return attributes
Exemplo n.º 2
0
    def write_attribute_type_rule(self, attribute, lo=None):
        if lo:
            formatted_name = lo['formatted_name']
            refname = lo['name']
            abbrev = strFunctions.abbrev_lo_name(refname)
        else:
            formatted_name = self.formatted_name
            refname = self.name
            abbrev = self.name
        att_type = attribute['type']
        [att_name_no_hyphen,
         unused] = strFunctions.remove_hyphens(attribute['name'])
        att_name = strFunctions.upper_first(att_name_no_hyphen)
        name = strFunctions.wrap_token(attribute['texname'], self.package)
        rule_type = 'String'
        if att_type == 'SId':
            return
        elif att_type == 'SIdRef':
            [ref_name, ref_type] = \
                strFunctions.get_sid_refs(attribute['element'])
            # hack for render
            if ref_name == 'StartHead' or ref_name == 'EndHead':
                ref_name = 'LineEnding'
            if ref_name == 'SBase':
                text = 'The value of the attribute {0} of {1} {2} object must be ' \
                       'the identifier of an existing object derived from the \SBase class and defined in the ' \
                       'enclosing \Model object.'\
                    .format(name, self.indef, formatted_name, ref_name)
            else:
                text = 'The value of the attribute {0} of {1} {2} object must be ' \
                       'the identifier of an existing \{3} object defined in the ' \
                       'enclosing \Model object.'\
                    .format(name, self.indef, formatted_name, ref_name)
            rule_type = ref_type
        elif att_type == 'string':
            text = 'The attribute {0} on {1} {2} must have a value of data ' \
                   'type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token('string'))
        elif att_type == 'ID':
            text = 'The attribute {0} on {1} {2} must have a value of XML data ' \
                   'type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token('ID'))
        elif att_type == 'IDREF':
            text = 'The value of the attribute {0} of {1} {2} object must be ' \
                   'the \'metaid\' of an existing \SBase object defined in the ' \
                   'enclosing \Model object.'\
                .format(name, self.indef, formatted_name)
            rule_type = 'SBase'
        elif att_type == 'int' or att_type == 'uint':
            text = 'The attribute {0} on {1} {2} must have a value of data ' \
                   'type {3}{4}'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token('integer'),
                        '.' if att_type == 'int' else ', and must be non negative.')
            rule_type = 'Integer' if att_type == 'int' else 'NonNegativeInteger'
        elif att_type == 'double':
            text = 'The attribute {0} on {1} {2} must have a value of data ' \
                   'type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token('double'))
            rule_type = 'Double'
        elif att_type == 'boolean' or att_type == 'bool':
            text = 'The attribute {0} on {1} {2} must have a value of data ' \
                   'type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token('boolean'))
            rule_type = 'Boolean'
        elif att_type == 'UnitSId' or att_type == 'UnitSIdRef':
            text = 'The value of the attribute {0} on {1} {2} must have a ' \
                   'taken from the following: the identifier of a ' \
                   '\\UnitDefinition object in the enclosing \Model, or one ' \
                   'of the base units in SBML.'.format(name,
                                                       self.indef,
                                                       formatted_name)
            rule_type = 'UnitSId'
        elif att_type == 'enum':
            enum_name = strFunctions.texify(attribute['element'])
            enums = attribute['parent']['root']['enums']
            enum_values = self.parse_enum_values(attribute['element'], enums)
            text = 'The value of the attribute {0} of {1} {2} object must ' \
                   'conform to the syntax of SBML data type {3} and ' \
                   'may only take on the allowed values of {3} defined ' \
                   'in SBML; that is, the value must be one of the ' \
                   'following: {4}.'.format(name, self.indef,
                                            formatted_name,
                                            strFunctions.wrap_enum(enum_name),
                                            enum_values)
            rule_type = '{0}Enum'.format(attribute['element'])
        elif att_type == 'array':
            array_type = strFunctions.lower_first(attribute['element'])
            text = 'The value of the attribute {0} of {1} {2} object must ' \
                   'be an array of values of type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token(array_type))
        elif att_type == 'vector':
            array_type = strFunctions.lower_first(attribute['element'])
            text = 'The value of the attribute {0} of {1} {2} object must ' \
                   'be an vector of values of type {3}.'\
                .format(name, self.indef, formatted_name,
                        strFunctions.wrap_token(array_type))
        elif att_type == 'element' and attribute['element'] == 'RelAbsVector':
            text = 'The value of the attribute {0} of {1} {2} object must ' \
                   'conform to the syntax of SBML data type \\RelAbsVector, ' \
                   'i.e., a string encoding optionally an absolute number ' \
                   'followed by an optional relative number followed ' \
                   'by a \\% sign. Adding spaces between the ' \
                   'coordinates is encouraged, but not required.'\
                .format(name, self.indef, formatted_name)
        else:
            text = 'FIXME: Encountered an unknown attribute type {0} in ' \
                   'ValidationRulesForClass'\
                .format(att_type)
#            global_variables.code_returned = \
#                global_variables.return_codes['unknown type used']

        ref = '{0}, {1}.'\
            .format(self.pkg_ref, strFunctions.wrap_section(refname))
        sev = 'ERROR'
        lib_sev = '{0}_SEV_ERROR'.format(global_variables.up_full_lib)
        if att_type == 'SIdRef' or att_type == 'IDREF':
            short = 'The attribute \'{0}\' must point to {1} object.'.format(
                strFunctions.lower_first(att_name), rule_type)
        else:
            short = 'The \'{0}\' attribute must be {1}.'.format(
                strFunctions.lower_first(att_name), rule_type)

        lib_ref = 'L3V1 {0} V1 Section'.format(self.up_package)
        tc = '{0}{1}{2}MustBe{3}'.format(self.up_package, abbrev, att_name,
                                         rule_type)
        return dict({
            'number': self.number,
            'text': text,
            'reference': ref,
            'severity': sev,
            'typecode': tc,
            'lib_sev': lib_sev,
            'short': short,
            'lib_ref': lib_ref,
            'object': refname,
            'attrib': att_name,
            'attrib_type': att_type
        })
    def write_get_object(self):
        if not self.is_cpp_api:
            return
        elif self.is_list_of:
            return

        if len(self.elements) == 0:
            return

        # create comment parts
        params = []
        return_lines = []
        additional = []
        title_line = 'Returns the nth object of \"objectName" in this {0}.' \
            .format(self.class_name)
        params.append(
            '@param elementName, the name of the element to get number of.')
        params.append(
            '@param index, unsigned int the index of the object to retrieve.')

        return_lines.append('@return pointer to the object.')

        # create the function declaration
        function = 'getObject'
        return_type = '{0}*'.format(global_variables.baseClass)

        arguments = ['const std::string& elementName', 'unsigned int index']

        code = []
        if not self.has_elements_with_same_xml_name():
            # create the function implementation
            first_line = ['{0}* obj = NULL'.format(global_variables.baseClass)]
            last_line = ['return obj']
            first = True
            block = []
            if_block = []

            for elem in self.elements:
                if not first:
                    block.append('else if')
                else:
                    first = False
                block.append('elementName == \"{0}\"'.format(elem['name']))
                [elem_name, unused] = strFunctions.remove_hyphens(elem['name'])
                if elem in self.single_elements:
                    block.append('return get{0}()'.format(
                        strFunctions.upper_first(elem_name)))
                else:
                    block.append('return get{0}(index)'.format(
                        strFunctions.upper_first(elem_name)))

                if len(block) > 2:
                    if_block = self.create_code_block('else_if', block)
                else:
                    if_block = self.create_code_block('if', block)
            code = [
                self.create_code_block('line', first_line), if_block,
                self.create_code_block('line', last_line)
            ]
        else:
            code = [
                self.create_code_block('comment', ['TO DO']),
                self.create_code_block('line', ['return NULL'])
            ]

        # return the parts
        return dict({
            'title_line': title_line,
            'params': params,
            'return_lines': return_lines,
            'additional': additional,
            'function': function,
            'return_type': return_type,
            'arguments': arguments,
            'constant': False,
            'virtual': True,
            'object_name': self.struct_name,
            'implementation': code
        })
    def write_get_num_objects(self):
        if not self.is_cpp_api:
            return
        elif self.is_list_of:
            return

        if len(self.elements) == 0:
            return

        # create comment parts
        params = []
        return_lines = []
        additional = []
        title_line = 'Returns the number of \"elementName" in this {0}.' \
            .format(self.class_name)
        params.append(
            '@param elementName, the name of the element to get number of.')

        return_lines.append('@return unsigned int number of elements.')

        # create the function declaration
        function = 'getNumObjects'
        return_type = 'unsigned int'

        arguments = ['const std::string& elementName']

        code = []
        if not self.has_elements_with_same_xml_name():
            # create the function implementation
            first_line = ['unsigned int n = 0']
            last_line = ['return n']
            first = True
            block = []
            if_block = []

            for elem in self.elements:
                if not first:
                    block.append('else if')
                else:
                    first = False
                block.append('elementName == \"{0}\"'.format(elem['name']))
                if elem in self.lo_elements:
                    name = strFunctions.plural(
                        strFunctions.upper_first(elem['name']))
                    block.append('return getNum{0}()'.format(name))
                else:
                    [elem_name,
                     unused] = strFunctions.remove_hyphens(elem['name'])
                    nested_if = [
                        'isSet{0}()'.format(
                            strFunctions.upper_first(elem_name)), 'return 1'
                    ]
                    nested_if_block = self.create_code_block('if', nested_if)
                    block.append(nested_if_block)
                if len(block) > 2:
                    if_block = self.create_code_block('else_if', block)
                else:
                    if_block = self.create_code_block('if', block)
            code = [
                self.create_code_block('line', first_line), if_block,
                self.create_code_block('line', last_line)
            ]
        else:
            code = [
                self.create_code_block('comment', ['TO DO']),
                self.create_code_block('line', ['return 0'])
            ]

        # return the parts
        return dict({
            'title_line': title_line,
            'params': params,
            'return_lines': return_lines,
            'additional': additional,
            'function': function,
            'return_type': return_type,
            'arguments': arguments,
            'constant': False,
            'virtual': True,
            'object_name': self.struct_name,
            'implementation': code
        })
    def write_remove_object(self):
        if not self.is_cpp_api:
            return
        elif self.is_list_of:
            return

        if len(self.elements) == 0:
            return

        # create comment parts
        params = []
        return_lines = []
        additional = []
        title_line = 'Removes and returns the new "elementName" object with the given id in this {0}.' \
            .format(self.class_name)
        params.append('@param elementName, the name of the element to remove.')
        params.append('@param id, the id of the element to remove.')

        return_lines.append('@return pointer to the element removed.')

        # create the function declaration
        function = 'removeChildObject'
        return_type = '{0}*'.format(global_variables.baseClass)

        arguments = ['const std::string& elementName', 'const std::string& id']

        code = []
        if not self.has_elements_with_same_xml_name():
            # create the function implementation
            last_line = ['return NULL']
            first = True
            block = []
            if_block = []

            for elem in self.elements:
                if elem['concrete']:
                    for conc in elem['concrete']:
                        if not first:
                            block.append('else if')
                        else:
                            first = False
                        elemName = elem['name']
                        if not elem['element'] or elem['element'] == elemName:
                            elemElem = elemName
                        else:
                            elemElem = elem['element']
                        block.append('elementName == \"{0}\"'.format(
                            conc['name']))
                        single = True
                        if elem not in self.single_elements:
                            thisClass = query.get_class(
                                elemElem, self.classroot)
                            single = False
                            hasid = False
                            for att in thisClass['attribs']:
                                if att['name'] == 'id':
                                    hasid = True
                            if hasid:
                                block.append('return remove{0}(id)'.format(
                                    strFunctions.upper_first(elemName)))
                            else:
                                nested_if = self.create_code_block(
                                    'if', [
                                        'get{0}(i)->getId() == id'.format(
                                            strFunctions.upper_first(elemName)
                                        ), 'return remove{0}(i)'.format(
                                            strFunctions.upper_first(elemName))
                                    ])
                                nested_for = self.create_code_block(
                                    'for', [
                                        'unsigned int i = 0; i < getNum{0}(); i++'
                                        ''.format(
                                            strFunctions.plural(
                                                strFunctions.upper_first(
                                                    elemName))), nested_if
                                    ])
                                block.append(nested_for)
                        else:
                            [elem_name,
                             unused] = strFunctions.remove_hyphens(elemName)
                            block.append('{0} * obj = get{1}()'.format(
                                elemElem, strFunctions.upper_first(elem_name)))
                            block.append(
                                'if (unset{0}() == LIBSBML_OPERATION_SUCCESS) return obj'
                                .format(strFunctions.upper_first(elem_name)))
                else:
                    if not first:
                        block.append('else if')
                    else:
                        first = False
                    elemName = elem['name']
                    if not elem['element'] or elem['element'] == elemName:
                        elemElem = elemName
                    else:
                        elemElem = elem['element']
                    block.append('elementName == \"{0}\"'.format(elem['name']))
                    single = True
                    if elem not in self.single_elements:
                        thisClass = query.get_class(elemElem, self.classroot)
                        single = False
                        hasid = False
                        for att in thisClass['attribs']:
                            if att['name'] == 'id':
                                hasid = True
                        if hasid:
                            block.append('return remove{0}(id)'.format(
                                strFunctions.upper_first(elemName)))
                        else:
                            nested_if = self.create_code_block(
                                'if', [
                                    'get{0}(i)->getId() == id'.format(
                                        strFunctions.upper_first(elemName)),
                                    'return remove{0}(i)'.format(
                                        strFunctions.upper_first(elemName))
                                ])
                            nested_for = self.create_code_block(
                                'for', [
                                    'unsigned int i = 0; i < getNum{0}(); i++'
                                    ''.format(
                                        strFunctions.plural(
                                            strFunctions.upper_first(
                                                elemName))), nested_if
                                ])
                            block.append(nested_for)
                    else:
                        [elem_name,
                         unused] = strFunctions.remove_hyphens(elemName)
                        block.append('{0} * obj = get{1}()'.format(
                            elemElem, strFunctions.upper_first(elem_name)))
                        block.append(
                            'if (unset{0}() == LIBSBML_OPERATION_SUCCESS) return obj'
                            .format(strFunctions.upper_first(elem_name)))
                if single:
                    if len(block) > 3:
                        if_block = self.create_code_block('else_if', block)
                    else:
                        if_block = self.create_code_block('if', block)
                else:
                    if len(block) > 2:
                        if_block = self.create_code_block('else_if', block)
                    else:
                        if_block = self.create_code_block('if', block)
            code = [if_block, self.create_code_block('line', last_line)]
        else:
            code = [
                self.create_code_block('comment', ['TO DO']),
                self.create_code_block('line', ['return NULL'])
            ]

        # return the parts
        return dict({
            'title_line': title_line,
            'params': params,
            'return_lines': return_lines,
            'additional': additional,
            'function': function,
            'return_type': return_type,
            'arguments': arguments,
            'constant': False,
            'virtual': True,
            'object_name': self.struct_name,
            'implementation': code
        })
    def write_add_object(self):
        if not self.is_cpp_api:
            return
        elif self.is_list_of:
            return

        if len(self.elements) == 0:
            return

        # create comment parts
        params = []
        return_lines = []
        additional = []
        title_line = 'Adds a new "elementName" object to this {0}.' \
            .format(self.class_name)
        params.append('@param elementName, the name of the element to create.')
        params.append('@param element, pointer to the element to be added.')

        return_lines.append('@copydetails doc_returns_success_code')
        return_lines.append('@li @{0}constant{1}{2}, '
                            ' OperationReturnValues_'
                            't{3}'.format(self.language, self.open_br,
                                          self.success, self.close_br))
        return_lines.append('@li @{0}constant{1}{2},'
                            ' OperationReturnValues_'
                            't{3}'.format(self.language, self.open_br,
                                          self.failed, self.close_br))

        # create the function declaration
        function = 'addChildObject'
        return_type = 'int'

        arguments = [
            'const std::string& elementName',
            'const {0}* element'.format(global_variables.baseClass)
        ]

        code = []
        if not self.has_elements_with_same_xml_name():
            # create the function implementation
            last_line = ['return LIBSBML_OPERATION_FAILED']
            first = True
            block = []
            if_block = []

            for elem in self.elements:
                if elem['concrete']:
                    for conc in elem['concrete']:
                        if not first:
                            block.append('else if')
                        else:
                            first = False
                        elemName = elem['name']
                        if not elem['element'] or elem['element'] == elemName:
                            elemElem = elemName
                        else:
                            elemElem = elem['element']
                        block.append(
                            'elementName == \"{0}\" && element->getTypeCode() == {1}'
                            .format(conc['name'], conc['typecode']))
                        if elem not in self.single_elements:
                            block.append(
                                'return add{0}((const {1}*)(element))'.format(
                                    strFunctions.upper_first(elemName),
                                    elemElem))
                        else:
                            block.append(
                                'return set{0}((const {1}*)(element))'.format(
                                    strFunctions.upper_first(elemName),
                                    elemElem))
                else:
                    if not first:
                        block.append('else if')
                    else:
                        first = False
                    elemName = elem['name']
                    if not elem['element'] or elem['element'] == elemName:
                        elemElem = elemName
                    else:
                        elemElem = elem['element']
                    [elem_name, unused] = strFunctions.remove_hyphens(elemName)
                    block.append(
                        'elementName == \"{0}\" && element->getTypeCode() == {1}'
                        .format(elemName, elem['typecode']))
                    if elem not in self.single_elements:
                        block.append(
                            'return add{0}((const {1}*)(element))'.format(
                                strFunctions.upper_first(elem_name), elemElem))
                    else:
                        block.append(
                            'return set{0}((const {1}*)(element))'.format(
                                strFunctions.upper_first(elem_name), elemElem))

                if len(block) > 2:
                    if_block = self.create_code_block('else_if', block)
                else:
                    if_block = self.create_code_block('if', block)
            code = [if_block, self.create_code_block('line', last_line)]
        else:
            code = [
                self.create_code_block('comment', ['TO DO']),
                self.create_code_block('line', ['return -1'])
            ]

        # return the parts
        return dict({
            'title_line': title_line,
            'params': params,
            'return_lines': return_lines,
            'additional': additional,
            'function': function,
            'return_type': return_type,
            'arguments': arguments,
            'constant': False,
            'virtual': True,
            'object_name': self.struct_name,
            'implementation': code
        })
    def write_create_object(self):
        if not self.is_cpp_api:
            return
        elif self.is_list_of:
            return

        if len(self.elements) == 0:
            return

        # create comment parts
        params = []
        return_lines = []
        additional = []
        title_line = 'Creates and returns an new "elementName" object in this {0}.' \
            .format(self.class_name)
        params.append('@param elementName, the name of the element to create.')

        return_lines.append('@return pointer to the element created.')

        # create the function declaration
        function = 'createChildObject'
        #        if self.is_plugin:
        return_type = '{0}*'.format(global_variables.baseClass)

        arguments = ['const std::string& elementName']

        code = []
        # create the function implementation
        if self.is_plugin:
            first_line = ['{0}* obj = NULL'.format(global_variables.baseClass)]
        else:
            first_line = ['{0}* obj = NULL'.format(self.base_class)]

        last_line = ['return obj']
        if not self.has_elements_with_same_xml_name():
            first = True
            block = []
            if_block = []

            for elem in self.elements:
                if elem['concrete']:
                    for conc in elem['concrete']:
                        if not first:
                            block.append('else if')
                        else:
                            first = False
                        concname = conc['name']
                        concelem = conc['name']
                        if conc['name'].lower() != conc['element'].lower():
                            concelem = strFunctions.lower_first(
                                strFunctions.remove_prefix(conc['element']))
                            # hack for render
                            if self.package == 'Render' or self.package == 'render':
                                remove_prefix = True
                                prefix_to_remove = strFunctions.upper_first(
                                    self.package)
                                concelem = strFunctions.remove_prefix(
                                    conc['element'], False, remove_prefix,
                                    prefix_to_remove)

                        block.append('elementName == \"{0}\"'.format(concname))
                        block.append('return create{0}()'.format(
                            strFunctions.upper_first(concelem)))
                        if len(block) > 2:
                            if_block = self.create_code_block('else_if', block)
                        else:
                            if_block = self.create_code_block('if', block)
                else:
                    if not first:
                        block.append('else if')
                    else:
                        first = False
                    block.append('elementName == \"{0}\"'.format(elem['name']))
                    [elem_name,
                     unused] = strFunctions.remove_hyphens(elem['name'])
                    block.append('return create{0}()'.format(
                        strFunctions.upper_first(elem_name)))
                    if len(block) > 2:
                        if_block = self.create_code_block('else_if', block)
                    else:
                        if_block = self.create_code_block('if', block)
            code = [
                self.create_code_block('line', first_line), if_block,
                self.create_code_block('line', last_line)
            ]
        else:
            code = [
                self.create_code_block('line', first_line),
                self.create_code_block('comment', ['TO DO']),
                self.create_code_block('line', last_line)
            ]

        # return the parts
        return dict({
            'title_line': title_line,
            'params': params,
            'return_lines': return_lines,
            'additional': additional,
            'function': function,
            'return_type': return_type,
            'arguments': arguments,
            'constant': False,
            'virtual': True,
            'object_name': self.struct_name,
            'implementation': code
        })