Skip to content
Snippets Groups Projects
tosca2doc.py 6 KiB
Newer Older
carignani's avatar
carignani committed
#!/usr/bin/python2.7
'''
Parses a TOSCA template and generates a docx file
'''


import sys
import toscaparser.utils.yamlparser as yaml

import docx
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT

PRINT_TRESHOLD = 1

TEMPLATES = {}

FNS = {
    'VNFD' : 'etsi_nfv_sol001_vnfd_2_5_1_types.yaml',
    'NSD'  : 'etsi_nfv_sol001_nsd_2_5_1_types.yaml',
    'PNFD' : 'etsi_nfv_sol001_pnfd_2_5_1_types.yaml'
}

TOSCA_TYPES = [
    'data_types',
    'artifact_types',
    'capability_types',
    'requirements_types',
    'relationship_types',
    'interface_types',
    'node_types',
    'group_types',
    'policy_types'
]

TOSCA_TYPES_PRETTYPRINT = {
    'data_types': 'Data Types',
    'artifact_types': 'Artifact Types',
    'capability_types': 'Capability Types',
    'requirements_types': 'Requirements types',
    'relationship_types': 'Relationship Types',
    'interface_types': 'Interface Types',
    'node_types': 'Node Types',
    'group_types': 'Group Types',
    'policy_types': 'Policy Types'
}


IDS = [6, 2, 1, 1]

def load_template(file_path, templs, key):
    '''
    Loads the content of the file at file_patch into the YAML templates array
    '''
    yaml_data = open(file_path).read()
    #print("+++++++++++++++++++++++++++++++++++++")
    #print(yaml_data)
    #print("+++++++++++++++++++++++++++++++++++++")
    templs[key] = yaml.simple_ordered_parse(yaml_data)

def print_lvl(num, txt):
    if num + 1 > PRINT_TRESHOLD:
        return
    index = ".".join(map(str, IDS[:(num+1)]))
    print index +  " " + ('-'*(num+1)) + ' ' + txt

def add_heading_with_num(num, txt, doc):
    '''
    Add a new heading to the document, with the calculated index number
    '''
    index = ".".join(map(str, IDS[:(num+1)]))
    doc.add_heading(index + " " + txt, num)

def cell_text_bold(cell):
    cell.paragraphs[0].runs[0].font.bold = True

def cell_text_centered(cell):
    cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

def mk_props_table_hdr(table):
    hdr_cells = table.rows[0].cells
    hdr_cells[0].text = 'Name'
    hdr_cells[1].text = 'Required'
    hdr_cells[2].text = 'Type'
    hdr_cells[3].text = 'Constraints'
    hdr_cells[4].text = 'Description'
    map(cell_text_bold, hdr_cells)
    map(cell_text_centered, hdr_cells)

def dt_name_from_path(dt_path):
    return dt_path.split('.')[-1]

def prop_field_to_str(prop_field):
    if type(prop_field) == bool:
        return 'yes' if prop_field else 'no'
    return str(prop_field)

def add_prop_row(prop_name, prop_fields, table):
    '''
    Add a row to table and fills it with info from prop
    '''
    nrow = table.add_row()
    prop_cells = nrow.cells
    prop_cells[0].text = prop_name

    all_fields = ['required', 'type', 'constraints', 'description']

    counter = 1
    for field in all_fields:
        if field in prop_fields:
            prop_cells[counter].text = prop_field_to_str(prop_fields[field])
        counter = counter + 1

def print_all_types(templ, lvl, doc):
    for tosca_type in TOSCA_TYPES:
        if not tosca_type in templ:
            continue
        print_lvl(lvl, tosca_type)
        add_heading_with_num(lvl, TOSCA_TYPES_PRETTYPRINT[tosca_type], doc)
        for data_type in templ[tosca_type]:
            print_lvl(lvl + 1, data_type)
            add_heading_with_num(lvl + 1, data_type, doc)

            if 'description' in templ[tosca_type][data_type]:
                print_lvl(lvl + 2, 'Description')
                add_heading_with_num(lvl + 2, 'Description', doc)
                doc.add_paragraph(templ[tosca_type][data_type]['description'])
                IDS[lvl+2] = IDS[lvl+2] + 1

            if 'properties' in templ[tosca_type][data_type]:
                print_lvl(lvl + 2, 'Properties')
                add_heading_with_num(lvl + 2, 'Properties', doc)
                # num_row = templ[tosca_type][data_type]['properties'].items()
                doc.add_paragraph("The properties of the "+
                    dt_name_from_path(data_type)
                    +" data type shall comply with the provisions set out in table REF_TBD.")
                table = doc.add_table(rows=1, cols=5)
                mk_props_table_hdr(table)
                for prop in templ[tosca_type][data_type]['properties']:
                    # print "PROP: " + prop + ", VAL: " + str(templ[tosca_type][data_type]['properties'][prop])
                    add_prop_row(prop, templ[tosca_type][data_type]['properties'][prop], table)
                IDS[lvl+2] = IDS[lvl+2] + 1

            print_lvl(lvl + 2, 'Definition')
            add_heading_with_num(lvl + 2, 'Definition', doc)
            doc.add_paragraph("The syntax of the "+
                dt_name_from_path(data_type)+
                " data type shall comply with the following definition:")
            def_table = doc.add_table(rows=1, cols=1)
            def_table.rows[0].cells[0].text = 'TBD'
            IDS[lvl+2] = IDS[lvl+2] + 1

            print_lvl(lvl + 2, 'Examples')
            add_heading_with_num(lvl + 2, 'Examples', doc)
            def_table = doc.add_table(rows=1, cols=1)
            def_table.rows[0].cells[0].text = 'TBD'
            IDS[lvl+2] = IDS[lvl+2] + 1

            print_lvl(lvl + 2, 'Additional Requirements')
            add_heading_with_num(lvl + 2, 'Additional Requirements', doc)
            doc.add_paragraph("None.")
            IDS[lvl+2] = IDS[lvl+2] + 1

            IDS[lvl+1] = IDS[lvl+1] + 1
            IDS[lvl+2] = 1

        IDS[lvl+1] = 1
        IDS[lvl] = IDS[lvl] + 1
    IDS[lvl] = 2

def generate_from_file(fn, doc, fpath):
    load_template(fpath, TEMPLATES, fn)
    print_lvl(0, fn)
    add_heading_with_num(0, fn, doc)
    print_all_types(TEMPLATES[fn], 1, doc)
    #print TEMPLATES[fn]

if __name__ == "__main__":
    doc = docx.Document()

    if len(sys.argv) < 2:
        print "Usage: robot2doc <robot_file_or_dir> [<out_file> [spec_section_title]]"
        sys.exit()

    FOLDR = sys.argv[1]

    print "Using folder: " + sys.argv[1]

    for fn in ['VNFD', 'NSD', 'PNFD']:
        generate_from_file(fn, doc, FOLDR + '/' + FNS[fn])
        IDS[0] = IDS[0] + 1

    doc.save('sol001.docx')