Esempio n. 1
0
File: xsd.py Progetto: ANZ-bank/Sysl
    def build_hierarchical_xsd():

        # Top level element
        with xs('element', name=context.model_class):
            with xs('complexType'):
                with xs('sequence', minOccurs=1, maxOccurs=1):
                    for (tname, ft, t) in syslx.sorted_types(context):
                        if 'xml_root' in syslx.patterns(t.attrs):
                            xs('element/', name=tname, type=tname, minOccurs=0)
                            break

        w(xsd_separator)

        for (tname, ft, t) in syslx.sorted_types(context):
            with xs('complexType', name=tname):

                with xs('all'):
                    for (fname, f) in sorted(t.tuple.attr_defs.iteritems()):
                        if 'xml_attribute' not in syslx.patterns(f.attrs):
                            if f.HasField('set'):
                                with xs('element', name=fname + 'List'):
                                    with xs('complexType'):
                                        with xs('sequence', maxOccurs='unbounded'):
                                            build_element(
                                                fname, f, True, False)
                            else:
                                build_element(fname, f, False, False)

                # attributes second
                for (fname, f) in sorted(t.tuple.attr_defs.iteritems()):
                    if 'xml_attribute' in syslx.patterns(f.attrs):
                        build_element(fname, f, False, True)
Esempio n. 2
0
    def build_hierarchical_xsd():

        # Top level element
        with xs('element', name=context.model_class):
            with xs('complexType'):
                with xs('sequence', minOccurs=1, maxOccurs=1):
                    for (tname, ft, t) in syslx.sorted_types(context):
                        if 'xml_root' in syslx.patterns(t.attrs):
                            xs('element/', name=tname, type=tname, minOccurs=0)
                            break

        w(xsd_separator)

        for (tname, ft, t) in syslx.sorted_types(context):
            with xs('complexType', name=tname):

                with xs('all'):
                    for (fname, f) in sorted(t.tuple.attr_defs.iteritems()):
                        if 'xml_attribute' not in syslx.patterns(f.attrs):
                            if f.HasField('set'):
                                with xs('element', name=fname + 'List'):
                                    with xs('complexType'):
                                        with xs('sequence',
                                                maxOccurs='unbounded'):
                                            build_element(
                                                fname, f, True, False)
                            else:
                                build_element(fname, f, False, False)

                # attributes second
                for (fname, f) in sorted(t.tuple.attr_defs.iteritems()):
                    if 'xml_attribute' in syslx.patterns(f.attrs):
                        build_element(fname, f, False, True)
Esempio n. 3
0
def _check_deps(module, validate):
    """Check app:endpoint dependencies."""
    deps = set()
    errors = []

    for (appname, app) in module.apps.iteritems():
        for epname in app.endpoints:
            endpt = app.endpoints[epname]

            for (_, call) in syslalgo.enumerate_calls(endpt.stmt):
                targetname = syslx.fmt_app_name(call.target)
                if targetname not in module.apps:
                    errors.append('{} <- {}: calls non-existent app {}'.format(
                        appname, epname, targetname))
                else:
                    target = module.apps[targetname]
                    assert 'abstract' not in syslx.patterns(target.attrs), (
                        "call target '{}' must not be ~abstract".format(targetname))
                    if call.endpoint not in target.endpoints:
                        errors.append(
                            '{} <- {}: calls non-existent endpoint {} -> {}'.format(
                                appname, epname, targetname, call.endpoint))
                    else:
                        deps.add(
                            ((appname, epname), (targetname, call.endpoint)))

    if errors and validate:
        raise Exception('broken deps:\n  ' + '\n  '.join(errors))

    return deps
Esempio n. 4
0
    def new_var(var, appname):
        """Outputs a new definition when VarManager makes a new variable."""

        app = module.apps[appname]
        has_category = syslx.patterns(app.attrs) & {
            'human', 'cron', 'db', 'external', 'ui'}
        assert len(has_category) <= 1
        (order, agent) = {
            'human': (0, 'actor'),
            'ui': (1, 'boundary'),
            'cron': (2, 'control'),
            'db': (4, 'database'),
            'external': (5, 'control'),
        }.get(
            ''.join(has_category),
            (3, 'control'))

        isoctrl = []

        for ctrl in app.attrs.keys():
            if 'iso_ctrl' in ctrl:
                isoctrl.append(re.sub(r'iso_ctrl_(.*)_txt', r'\1', ctrl))

        label = params.appfmt(
            appname=appname,
            controls=', '.join(i for i in sorted(isoctrl)),
            **diagutil.attr_fmt_vars(app.attrs)
        ).replace(u'\n', ur'\n')
        var_names.append(
            ((order, int(var[1:])), u'{} "{}" as {}'.format(agent, label, var)))
Esempio n. 5
0
    def new_var(var, appname):
        """Outputs a new definition when VarManager makes a new variable."""

        app = module.apps[appname]
        has_category = syslx.patterns(
            app.attrs) & {'human', 'cron', 'db', 'external', 'ui'}
        assert len(has_category) <= 1
        (order, agent) = {
            'human': (0, 'actor'),
            'ui': (1, 'boundary'),
            'cron': (2, 'control'),
            'db': (4, 'database'),
            'external': (5, 'control'),
        }.get(''.join(has_category), (3, 'control'))

        isoctrl = []

        for ctrl in app.attrs.keys():
            if 'iso_ctrl' in ctrl:
                isoctrl.append(re.sub(r'iso_ctrl_(.*)_txt', r'\1', ctrl))

        label = params.appfmt(appname=appname,
                              controls=', '.join(i for i in sorted(isoctrl)),
                              **diagutil.attr_fmt_vars(app.attrs)).replace(
                                  u'\n', ur'\n')
        var_names.append(
            ((order, int(var[1:])), u'{} "{}" as {}'.format(agent, label,
                                                            var)))
Esempio n. 6
0
def _map_subscriptions(module):
    """Map pubsub subscriptions into direct calls."""
    for appname in module.apps:
        app = module.apps[appname]

        if 'abstract' in syslx.patterns(app.attrs):
            continue

        for epname in app.endpoints:
            endpt = app.endpoints[epname]

            if endpt.HasField('source'):
                src_app = module.apps[syslx.fmt_app_name(endpt.source)]
                src_ep_name = endpt.name.split(' -> ')[1]
                assert src_ep_name in src_app.endpoints, (appname, epname,
                                                          src_ep_name,
                                                          str(src_app))
                src_ep = src_app.endpoints[src_ep_name]

                # Add call to pubsub endpoint.
                stmt = src_ep.stmt.add()
                call = stmt.call
                call.target.CopyFrom(app.name)
                call.endpoint = endpt.name

                # Maybe add ret.
                ret_payload = syslalgo.return_payload(endpt.stmt)
                if ret_payload:
                    stmt = src_ep.stmt.add()
                    stmt.ret.payload = ret_payload
Esempio n. 7
0
def _check_deps(module, validate):
    """Check app:endpoint dependencies."""
    deps = set()
    errors = []

    for (appname, app) in module.apps.iteritems():
        for epname in app.endpoints:
            endpt = app.endpoints[epname]

            for (_, call) in syslalgo.enumerate_calls(endpt.stmt):
                targetname = syslx.fmt_app_name(call.target)
                if targetname not in module.apps:
                    errors.append('{} <- {}: calls non-existent app {}'.format(
                        appname, epname, targetname))
                else:
                    target = module.apps[targetname]
                    assert 'abstract' not in syslx.patterns(target.attrs), (
                        "call target '{}' must not be ~abstract".format(
                            targetname))
                    if call.endpoint not in target.endpoints:
                        errors.append(
                            '{} <- {}: calls non-existent endpoint {} -> {}'.
                            format(appname, epname, targetname, call.endpoint))
                    else:
                        deps.add(
                            ((appname, epname), (targetname, call.endpoint)))

    if errors and validate:
        raise Exception('broken deps:\n  ' + '\n  '.join(errors))

    return deps
Esempio n. 8
0
def _map_subscriptions(module):
    """Map pubsub subscriptions into direct calls."""
    for appname in module.apps:
        app = module.apps[appname]

        if 'abstract' in syslx.patterns(app.attrs):
            continue

        for epname in app.endpoints:
            endpt = app.endpoints[epname]

            if endpt.HasField('source'):
                src_app = module.apps[syslx.fmt_app_name(endpt.source)]
                src_ep_name = endpt.name.split(' -> ')[1]
                assert src_ep_name in src_app.endpoints, (
                    appname, epname, src_ep_name, str(src_app))
                src_ep = src_app.endpoints[src_ep_name]

                # Add call to pubsub endpoint.
                stmt = src_ep.stmt.add()
                call = stmt.call
                call.target.CopyFrom(app.name)
                call.endpoint = endpt.name

                # Maybe add ret.
                ret_payload = syslalgo.return_payload(endpt.stmt)
                if ret_payload:
                    stmt = src_ep.stmt.add()
                    stmt.ret.payload = ret_payload
Esempio n. 9
0
 def find_apps(matching_apps):
     """Yield all apps that are relevant to this view."""
     exclude = set(args.exclude)
     for ((app1, _), (app2, _)) in deps:
         if not ({app1, app2} & exclude) and ({app1, app2} & matching_apps):
             for app in [app1, app2]:
                 if ('human' not in syslx.patterns(module.apps[app].attrs)):
                     yield app
Esempio n. 10
0
 def find_matching_apps(integrations):
     """Yield all apps that match the integrations."""
     exclude = set(args.exclude)
     app_re = re.compile(
         r'^(?:{})(?: *::|$)'.format('|'.join(integrations)))
     for ((app1, _), (app2, _)) in deps:
         if not ({app1, app2} & exclude):
             for app in [app1, app2]:
                 if app_re.match(app) and 'human' not in syslx.patterns(
                         module.apps[app].attrs):
                     yield app
Esempio n. 11
0
def export_model_js(module, appname, outpath, indent):
    '''The Model as JSON'''
    app = module.apps.get(appname)
    assert app, appname

    model = {}
    model['_version'] = '0.1'
    model['model'] = '_'.join(app.name.part)
    tables = model['types'] = {}

    for (tname, t) in app.types.iteritems():
        titem = tables[tname] = {}
        tmeta = titem['_'] = {}
        if t.HasField('relation'):
            tmeta['rel'] = True

        pkey = datamodel.primary_key_params(t, module)
        pkey_fields = {f for (_, f, _) in pkey}
        param_defs = [(typ, f) for (typ, _, f) in pkey]
        pk_param = ', '.join(f for (_, _, f) in pkey)

        fkeys = {
            java.name(fname): type_info
            for (fname, _, type_info) in datamodel.foreign_keys(t, module)
        }

        for (fname, f) in datamodel.sorted_fields(t):
            jfname = java.name(fname)
            (java_type, type_info, ftype) = datamodel.typeref(f, module)

            which_f = f.WhichOneof('type')
            if which_f == 'primitive':
                ftname = ftype.primitive
            elif fname in fkeys:
                fk_type_info = fkeys[fname]
                ftname = (fk_type_info.parent_path +
                          ('.' + fk_type_info.field
                           if fk_type_info.field != jfname else '='))

            if fname in pkey_fields:
                jfname += '*'
            elif 'required' in syslx.patterns(f.attrs):
                jfname += '!'

            fitem = titem[jfname] = [ftname]

            if len(fitem) == 1:
                fitem = titem[jfname] = fitem[0]

    out = cStringIO.StringIO()
    js_dump(appname, model, indent, out)
    open(outpath, 'w').write(out.getvalue())
Esempio n. 12
0
def export_model_js(module, appname, outpath, indent):
    '''The Model as JSON'''
    app = module.apps.get(appname)
    assert app, appname

    model = {}
    model['_version'] = '0.1'
    model['model'] = '_'.join(app.name.part)
    tables = model['types'] = {}

    for (tname, t) in app.types.iteritems():
        titem = tables[tname] = {}
        tmeta = titem['_'] = {}
        if t.HasField('relation'):
            tmeta['rel'] = True

        pkey = datamodel.primary_key_params(t, module)
        pkey_fields = {f for (_, f, _) in pkey}
        param_defs = [(typ, f) for (typ, _, f) in pkey]
        pk_param = ', '.join(f for (_, _, f) in pkey)

        fkeys = {java.name(fname): type_info
                 for (fname, _, type_info) in datamodel.foreign_keys(t, module)}

        for (fname, f) in datamodel.sorted_fields(t):
            jfname = java.name(fname)
            (java_type, type_info, ftype) = datamodel.typeref(f, module)

            which_f = f.WhichOneof('type')
            if which_f == 'primitive':
                ftname = ftype.primitive
            elif fname in fkeys:
                fk_type_info = fkeys[fname]
                ftname = (
                    fk_type_info.parent_path +
                    ('.' + fk_type_info.field if fk_type_info.field != jfname else '='))

            if fname in pkey_fields:
                jfname += '*'
            elif 'required' in syslx.patterns(f.attrs):
                jfname += '!'

            fitem = titem[jfname] = [ftname]

            if len(fitem) == 1:
                fitem = titem[jfname] = fitem[0]

    out = cStringIO.StringIO()
    js_dump(appname, model, indent, out)
    open(outpath, 'w').write(out.getvalue())
Esempio n. 13
0
    def inject(appname):
        app = module.apps[appname]
        if appname not in injected:
            for mixin in app.mixin2:
                mixin_app = inject(syslx.fmt_app_name(mixin.name))

                # Check for ~abstract
                assert 'abstract' in syslx.patterns(mixin_app.attrs), (
                    "mixin {} must be ~abstract".format(syslx.fmt_app_name(mixin.name)))

                for (epname, endpt) in mixin_app.endpoints.iteritems():
                    app.endpoints[epname].CopyFrom(endpt)

                for (tname, t) in mixin_app.types.iteritems():
                    app.types[tname].CopyFrom(t)

                for (vname, v) in mixin_app.views.iteritems():
                    app.views[vname].CopyFrom(v)

            injected.add(appname)

        return app
Esempio n. 14
0
    def inject(appname):
        app = module.apps[appname]
        if appname not in injected:
            for mixin in app.mixin2:
                mixin_app = inject(syslx.fmt_app_name(mixin.name))

                # Check for ~abstract
                assert 'abstract' in syslx.patterns(
                    mixin_app.attrs), ("mixin {} must be ~abstract".format(
                        syslx.fmt_app_name(mixin.name)))

                for (epname, endpt) in mixin_app.endpoints.iteritems():
                    app.endpoints[epname].CopyFrom(endpt)

                for (tname, t) in mixin_app.types.iteritems():
                    app.types[tname].CopyFrom(t)

                for (vname, v) in mixin_app.views.iteritems():
                    app.views[vname].CopyFrom(v)

            injected.add(appname)

        return app
Esempio n. 15
0
    def generate_state_view():

        def make_varmgr(istoplevel=False):
            """Return a variable manager instance."""
            appfmt = syslx.View(module.apps.get(
                args.project).attrs)['appfmt'].s
            appfmt = diagutil.parse_fmt(appfmt)

            def new_var(var, name):
                """Outputs a new definition when VarManager makes a new variable."""

                # TODO dodgy, should be using context (look at syslseqs)
                attrs = {}
                state_name = ''

                if istoplevel:
                    template = 'state "{}" as X{}{} {{'
                    attrs = module.apps[name].attrs
                    state_name = name
                else:
                    template = '  state "{}" as {}{}'
                    (app_name, _, ep_name) = name.partition(' : ')
                    attrs = module.apps[app_name].endpoints[ep_name].attrs
                    state_name = ep_name

                write(template,
                      appfmt(appname=state_name,
                             **diagutil.attr_fmt_vars(attrs)).replace('\n', r'\n'),
                      var,
                      ' <<highlight>>' if name in highlights else '')

            return diagutil.VarManager(new_var)

        with write.uml():

            if diagram_title:
                write('title ' + diagram_title)

            write('left to right direction')
            write('scale max 16384 height')
            write('hide empty description')
            write('skinparam state {{')
            write('  BackgroundColor FloralWhite')
            write('  BorderColor Black')
            write('  ArrowColor Crimson')
            if highlight_color:
                write('  BackgroundColor<<highlight>> ' + highlight_color)
            if arrow_color:
                write('  ArrowColor ' + arrow_color)
            if indirect_arrow_color and indirect_arrow_color != 'none':
                write('  ArrowColor<<indirect>> ' + indirect_arrow_color)
                write('  ArrowColor<<internal>> ' + indirect_arrow_color)
            write('}}')

            var_name = make_varmgr()
            tl_var_name = make_varmgr(True)

            clusters = {}

            # group end points and build the declarations
            for (app_a, ep_a), (app_b, ep_b) in integrations:

                if restrict_by and restrict_by not in module.apps[app_a].attrs.keys(
                ) + module.apps[app_b].attrs.keys():
                    continue

                if restrict_by and restrict_by not in module.apps[app_a].endpoints[ep_a].attrs.keys(
                ) + module.apps[app_b].endpoints[ep_b].attrs.keys():
                    continue

                if app_a not in clusters:
                    clusters[app_a] = set()
                if app_b not in clusters:
                    clusters[app_b] = set()

                client_ep = ep_b
                # create clients in the calling app
                clusters[app_a].add(ep_a)
                if app_a != app_b and not module.apps[app_a].endpoints[ep_a].is_pubsub:
                    clusters[app_a].add(client_ep + " client")

                clusters[app_b].add(ep_b)

            for cluster in clusters:
                tl_var_name(cluster)
                for member in clusters[cluster]:
                    var_name(cluster + ' : ' + member)
                write('}}')

            processed = []
            for ((app_a, ep_a), (app_b, ep_b)) in integrations:

                if restrict_by and restrict_by not in module.apps[app_a].attrs.keys(
                ) + module.apps[app_b].attrs.keys():
                    continue

                if restrict_by and restrict_by not in module.apps[app_a].endpoints[ep_a].attrs.keys(
                ) + module.apps[app_b].endpoints[ep_b].attrs.keys():
                    continue

                direct = {app_a, app_b} & highlights

                (match_app, match_ep) = (app_b, ep_b)

                # build the label
                label = ''
                needs_int = app_a != match_app

                pub_sub_src_ptrns = syslx.patterns(
                    module.apps[app_a].endpoints[ep_a].attrs)

                tgt_ptrns = syslx.patterns(module.apps[match_app].endpoints[match_ep].attrs) or \
                    syslx.patterns(module.apps[match_app].attrs)

                for stmt in yield_call_statements(
                        module.apps[app_a].endpoints[ep_a].stmt):

                    # if restrict_by not in stmt.attrs.keys():
                    #  continue

                    app_b_name = ' :: '.join(
                        part for part in stmt.call.target.part)

                    if match_app == app_b_name and match_ep == stmt.call.endpoint:
                        fmt_vars = diagutil.attr_fmt_vars(stmt.attrs)

                        src_ptrns = syslx.patterns(
                            stmt.attrs) or pub_sub_src_ptrns

                        ptrns = u', '.join(sorted(src_ptrns)) + u' → ' + u', '.join(sorted(tgt_ptrns)) \
                            if (bool(src_ptrns) or bool(tgt_ptrns)) else ''

                        label = diagutil.parse_fmt(app.attrs["epfmt"].s)(
                            needs_int=needs_int, patterns=ptrns, **fmt_vars)

                # if not label and middle:
                #  fmt_vars = diagutil.attr_fmt_vars(module.apps[app_b].endpoints[ep_b].attrs)
                #  label = diagutil.parse_fmt(app.attrs["epfmt"].s)(needs_int=needs_int, patterns=u'→' + middle + u'→', **fmt_vars)

                flow = ".".join([app_a, ep_b, app_b, ep_b])
                is_pubsub = module.apps[app_a].endpoints[ep_a].is_pubsub
                ep_b_client = ep_b + " client"
                if app_a != app_b:
                    if is_pubsub:
                        write('{} -{}> {}{}',
                              var_name(app_a + ' : ' + ep_a),
                              '[#blue]',
                              var_name(app_b + ' : ' + ep_b),
                              ' : ' + label if label else '')
                    else:
                        write('{} -{}> {}',
                              var_name(app_a + ' : ' + ep_a),
                              '[#' + indirect_arrow_color +
                              ']-' if indirect_arrow_color else '[#silver]-',
                              var_name(app_a + ' : ' + ep_b_client))
                        if flow not in processed:
                            write('{} -{}> {}{}',
                                  var_name(app_a + ' : ' + ep_b_client),
                                  '[#black]',
                                  var_name(app_b + ' : ' + ep_b),
                                  ' : ' + label if label else '')
                            processed.append(flow)

                else:
                    write('{} -{}> {}{}',
                          var_name(app_a + ' : ' + ep_a),
                          '[#' + indirect_arrow_color +
                          ']-' if indirect_arrow_color else '[#silver]-',
                          var_name(app_b + ' : ' + ep_b),
                          ' : ' + label if label else '')
Esempio n. 16
0
        def visit_stmts(stmts, deactivate, last_parent_stmt):
            """Recursively visit a stmt list."""
            def block(last_stmt, block_stmts, fmt, *args):
                """Output a compound block."""
                write(fmt, *args)
                with write.indent():
                    return visit_stmts(block_stmts, deactivate, last_stmt)

            def block_with_end(last_stmt, block_stmts, fmt, *args):
                """Output a compound block, including the 'end' clause."""
                payload = block(last_stmt, block_stmts, fmt, *args)
                write('end')
                return payload

            payload = None

            for (i, stmt) in enumerate(stmts):
                last_stmt = last_parent_stmt and i == len(stmts) - 1
                if stmt.HasField('call'):
                    with write.indent():
                        payload = visit_endpoint(
                            app,
                            syslx.fmt_app_name(stmt.call.target),
                            stmt.call.endpoint,
                            uptos,
                            app_patterns,
                            syslx.patterns(stmt.attrs) | syslx.patterns(
                                endpt.attrs),
                            stmt,
                            last_stmt and deactivate)
                elif stmt.HasField('action'):
                    #write('{0} -> {0} : {1}', agent, r'\n'.join(textwrap.wrap(stmt.action.action, 40)))
                    write('{0} -> {0} : {1}', agent, stmt.action.action)
                elif stmt.HasField('cond'):
                    payload = block_with_end(last_stmt, stmt.cond.stmt,
                                             'opt {}',
                                             stmt.cond.test)
                elif stmt.HasField('loop'):
                    payload = block_with_end(last_stmt, stmt.loop.stmt,
                                             'loop {} {}',
                                             stmt.loop.Mode.Name(
                                                 stmt.loop.mode),
                                             stmt.loop.criterion)
                elif stmt.HasField('loop_n'):
                    payload = block_with_end(last_stmt, stmt.loop_n.stmt,
                                             'loop {} times',
                                             stmt.loop_n.count)
                elif stmt.HasField('foreach'):
                    payload = block_with_end(last_stmt, stmt.foreach.stmt,
                                             'loop for each {}',
                                             stmt.foreach.collection)
                elif stmt.HasField('group'):
                    payload = block_with_end(last_stmt, stmt.group.stmt,
                                             'group {}',
                                             stmt.group.title)
                elif stmt.HasField('alt'):
                    prefix = 'alt'
                    for (j, choice) in enumerate(stmt.alt.choice):
                        last_alt_stmt = last_stmt and j == len(
                            stmt.alt.choice) - 1
                        payload = block(last_alt_stmt, choice.stmt,
                                        '{} {}', prefix, choice.cond)
                        prefix = 'else'
                    write('end')
                elif stmt.HasField('ret'):
                    rargs = []

                    for param in syslalgo.yield_ret_params(stmt.ret.payload):
                        if param != '...' and '.' in param:
                            (an, pn) = rex.split(r'\.', param)

                            rarg = format_args(an, pn)

                            if rarg:
                                rargs.append(rarg)
                        else:
                            rargs.append(param)

                    write('{}<--{} : {}', sender, agent,
                          ' | '.join(p for p in rargs))
                else:
                    raise Exception('No statement!')

            return payload
Esempio n. 17
0
    def visit_endpoint(
            from_app,
            appname,
            epname,
            uptos,
            sender_patterns,
            sender_endpt_patterns=None,
            stmt=None,
            deactivate=None):
        """Recursively visit an endpoint."""
        if from_app:
            sender = var_name(syslx.fmt_app_name(from_app.name))
        else:
            sender = '['
        agent = var_name(appname)
        app = module.apps.get(appname)
        endpt = app.endpoints.get(epname)
        assert endpt

        def visit_stmts(stmts, deactivate, last_parent_stmt):
            """Recursively visit a stmt list."""
            def block(last_stmt, block_stmts, fmt, *args):
                """Output a compound block."""
                write(fmt, *args)
                with write.indent():
                    return visit_stmts(block_stmts, deactivate, last_stmt)

            def block_with_end(last_stmt, block_stmts, fmt, *args):
                """Output a compound block, including the 'end' clause."""
                payload = block(last_stmt, block_stmts, fmt, *args)
                write('end')
                return payload

            payload = None

            for (i, stmt) in enumerate(stmts):
                last_stmt = last_parent_stmt and i == len(stmts) - 1
                if stmt.HasField('call'):
                    with write.indent():
                        payload = visit_endpoint(
                            app,
                            syslx.fmt_app_name(stmt.call.target),
                            stmt.call.endpoint,
                            uptos,
                            app_patterns,
                            syslx.patterns(stmt.attrs) | syslx.patterns(
                                endpt.attrs),
                            stmt,
                            last_stmt and deactivate)
                elif stmt.HasField('action'):
                    #write('{0} -> {0} : {1}', agent, r'\n'.join(textwrap.wrap(stmt.action.action, 40)))
                    write('{0} -> {0} : {1}', agent, stmt.action.action)
                elif stmt.HasField('cond'):
                    payload = block_with_end(last_stmt, stmt.cond.stmt,
                                             'opt {}',
                                             stmt.cond.test)
                elif stmt.HasField('loop'):
                    payload = block_with_end(last_stmt, stmt.loop.stmt,
                                             'loop {} {}',
                                             stmt.loop.Mode.Name(
                                                 stmt.loop.mode),
                                             stmt.loop.criterion)
                elif stmt.HasField('loop_n'):
                    payload = block_with_end(last_stmt, stmt.loop_n.stmt,
                                             'loop {} times',
                                             stmt.loop_n.count)
                elif stmt.HasField('foreach'):
                    payload = block_with_end(last_stmt, stmt.foreach.stmt,
                                             'loop for each {}',
                                             stmt.foreach.collection)
                elif stmt.HasField('group'):
                    payload = block_with_end(last_stmt, stmt.group.stmt,
                                             'group {}',
                                             stmt.group.title)
                elif stmt.HasField('alt'):
                    prefix = 'alt'
                    for (j, choice) in enumerate(stmt.alt.choice):
                        last_alt_stmt = last_stmt and j == len(
                            stmt.alt.choice) - 1
                        payload = block(last_alt_stmt, choice.stmt,
                                        '{} {}', prefix, choice.cond)
                        prefix = 'else'
                    write('end')
                elif stmt.HasField('ret'):
                    rargs = []

                    for param in syslalgo.yield_ret_params(stmt.ret.payload):
                        if param != '...' and '.' in param:
                            (an, pn) = rex.split(r'\.', param)

                            rarg = format_args(an, pn)

                            if rarg:
                                rargs.append(rarg)
                        else:
                            rargs.append(param)

                    write('{}<--{} : {}', sender, agent,
                          ' | '.join(p for p in rargs))
                else:
                    raise Exception('No statement!')

            return payload

        app_patterns = syslx.patterns(app.attrs)
        target_patterns = syslx.patterns(endpt.attrs)

        patterns = target_patterns

        human = 'human' in app_patterns
        human_sender = 'human' in sender_patterns
        cron = 'cron' in sender_patterns
        needs_int = not (human or human_sender or cron) and sender != agent
        label = re.sub(ur'^.*? -> ', u' ⬄ ', unicode(epname))

        cron = 'cron' in app_patterns

        if stmt:
            assert stmt.HasField('call')

            ptrns = ''
            if bool(sender_endpt_patterns) or bool(patterns):
                ptrns = u', '.join(sorted(sender_endpt_patterns)) + \
                    u' → ' + u', '.join(sorted(patterns))

            isoctrl = []

            for ctrl in endpt.attrs.keys():
                if 'iso_ctrl' in ctrl:
                    isoctrl.append(re.sub(r'iso_ctrl_(.*)_txt', r'\1', ctrl))

            epargs = []

            def format_args(an, pn):
                arg = '.'.join((an, pn))

                if arg:
                    conf = module.apps[an].types[pn].attrs['iso_conf'].s[:1].upper(
                    )
                    integ = module.apps[an].types[pn].attrs['iso_integ'].s[:1].upper(
                    )
                    isocolor = 'red' if 'R' in conf else 'green'
                    arg = '<color blue>' + arg + '</color>' + ' <<color ' + isocolor + '>' + \
                        (conf if conf else '?') + ', ' + \
                        (integ if integ else '?') + '</color>>'

                return arg

            for p in endpt.param:
                an = ' :: '.join(p.type.type_ref.ref.appname.part)
                pn = '.'.join(p.type.type_ref.ref.path)

                eparg = format_args(an, pn)

                if eparg:
                    epargs.append(eparg)

            label = params.epfmt(
                epname=label,
                human='human' if human else '',
                human_sender='human sender' if human_sender else '',
                needs_int='needs_int' if needs_int else '',
                args=' | '.join(e for e in epargs),
                #args=', '.join(p.name for p in stmt.call.arg),
                patterns=ptrns,
                controls=', '.join(i for i in sorted(isoctrl)),
                **diagutil.attr_fmt_vars(stmt.attrs)
            ).replace('\n', r'\n')

        if not ((human and sender == '[') or cron):
            ep_patterns = syslx.patterns(endpt.attrs)

            icon = '<&timer> ' if 'cron' in ep_patterns else ''
            write('{}->{} : {}{}', sender, agent, icon, label)
            if log_integration and stmt:
                log_integration(app=from_app, stmt=stmt, patterns=patterns)

        rargs = []

        for param in syslalgo.yield_ret_params(
                syslalgo.return_payload(endpt.stmt)):
            if param != '...' and '.' in param:
                (an, pn) = rex.split(r'\.', param)

                rarg = format_args(an, pn)

                if rarg:
                    rargs.append(rarg)
            else:
                rargs.append(param)

        payload = ' | '.join(p for p in rargs)

        calling_self = from_app and syslx.fmt_app_name(
            from_app.name) == appname
        if not calling_self and not payload and deactivate:
            deactivate()

        if len(endpt.stmt):
            hit_blackbox = False
            for (upto, comment) in itertools.chain(
                    uptos.iteritems(), already_visited.keys()):
                # Compare the common prefix of the current endpt and upto.
                upto_parts = upto.split(' <- ')
                if [appname, epname][:len(upto_parts)] == upto_parts:
                    hit_blackbox = True
                    if payload:
                        write.activate(agent)
                        if comment is not None:
                            write('note over {}: {}', agent,
                                  comment or 'see below')
                    else:
                        if comment is not None:
                            write('note {}: {}',
                                  'left' if sender > agent else 'right',
                                  comment or 'see below')
                    if payload:
                        write('{}<--{} : {}', sender, agent, payload)
                        write.deactivate(agent)
                    break

            if not hit_blackbox:
                with write.activated(agent, human or cron) as deactivate:
                    # 'see above')
                    visiting = (appname + ' <- ' + epname, None)
                    already_visited[visiting] += 1
                    try:
                        return visit_stmts(endpt.stmt, deactivate, True)
                    finally:
                        already_visited[visiting] -= 1
                        if not already_visited[visiting]:
                            del already_visited[visiting]
Esempio n. 18
0
def serializer(context):
    (app, module, package, model_class, write_file, _, _) = context

    facade = bool(context.wrapped_model)

    w = writer.Writer('java')

    java.Package(w, package)

    java.StandardImports(w)

    java.Import(w, 'java.text.ParseException')
    w.head()
    java.Import(w, 'javax.xml.stream.XMLStreamException')
    java.Import(w, 'javax.xml.stream.XMLStreamWriter')
    w.head()
    java.Import(w, 'org.joda.time.format.DateTimeFormatter')
    java.Import(w, 'org.joda.time.format.ISODateTimeFormat')

    if facade:
        model_name = syslx.fmt_app_name(context.wrapped_model.name)
        modelpkg = syslx.View(context.wrapped_model.attrs)['package'].s
        w.head()
        java.Import(w, modelpkg + '.*')
    else:
        modelpkg = package

    with java.Class(w,
                    '\n{}XmlSerializer'.format(model_class),
                    write_file,
                    package=package):
        with java.Method(w,
                         '\npublic',
                         'void',
                         'serialize',
                         [(model_class, 'facade' if facade else 'model'),
                          ('XMLStreamWriter', 'xsw')],
                         throws=['XMLStreamException']):
            if facade:
                w('{} model = facade.getModel();', model_name)

            w('xsw.writeStartElement("{}");', model_class)
            for (tname, ft, t) in syslx.sorted_types(context):
                if t.WhichOneof('type') == 'relation':
                    w('serialize(model.get{0}Table(), xsw, "{0}");', tname)
            w('xsw.writeEndElement();')

        for (tname, ft, t) in syslx.sorted_types(context):
            java.SeparatorComment(w)

            if t.WhichOneof('type') in ['relation', 'tuple']:
                with java.Method(w,
                                 '\npublic',
                                 'void',
                                 'serialize',
                                 [(modelpkg + '.' + tname + '.View', 'view'),
                                  ('XMLStreamWriter', 'xsw'),
                                  ('String', 'tag')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'view == null || view.isEmpty()'):
                        w('return;')
                    if t.WhichOneof('type') == 'relation':
                        w('xsw.writeStartElement("{}List");', tname)
                    order = [
                        o.s for o in syslx.View(t.attrs)['xml_order'].a.elt
                    ]
                    if order:
                        order_logic = []
                        for o in order:
                            order_logic.append(
                                '            i = io.sysl.ExprHelper.doCompare'
                                '(a.get{0}(), b.get{0}());\n'
                                '            if (i != 0) return i;\n'.format(
                                    java.CamelCase(o)))
                        order_by = (
                            '.orderBy(\n'
                            '    new java.util.Comparator<{0}> () {{\n'
                            '        @Override\n'
                            '        public int compare({0} a, {0} b) {{\n'
                            '            int i;\n'
                            '{1}'
                            '            return 0;\n'
                            '        }}\n'
                            '    }})\n').format(tname, ''.join(order_logic))
                    else:
                        order_by = ''

                    with java.For(w, '{} item : view{}',
                                  modelpkg + '.' + tname, order_by):
                        w('serialize(item, xsw, tag);', tname)
                    if t.WhichOneof('type') == 'relation':
                        w('xsw.writeEndElement();')

                with java.Method(w,
                                 '\npublic',
                                 'void',
                                 'serialize',
                                 [(modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    w('serialize(entity, xsw, "{}");', tname)

                with java.Method(w,
                                 '\npublic',
                                 'void',
                                 'serialize',
                                 [(modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw'),
                                  ('String', 'tag')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'entity == null'):
                        w('return;')
                    w('xsw.writeStartElement(tag);', tname)
                    for wantAttrs in [True, False]:
                        for (fname, f) in datamodel.sorted_fields(t):
                            jfname = java.name(fname)
                            method = java.CamelCase(jfname)
                            tref = datamodel.typeref(f, module)
                            type_ = tref[2]
                            if not type_:
                                continue
                            extra = ''
                            which_type = type_.WhichOneof('type')
                            if which_type == 'primitive':
                                extra = XML_GEN_MAP[type_.primitive]
                                if type_.primitive == type_.DECIMAL:
                                    for c in type_.constraint:
                                        if c.scale:
                                            access = 'round(entity.get{}(), {})'.format(
                                                method, c.scale)
                                            break
                                    else:
                                        access = 'round(entity.get{}(), 0)'.format(
                                            method)
                                else:
                                    access = 'entity.get{}()'.format(method)
                            elif which_type == 'enum':
                                access = 'entity.get{}().getValue()'.format(
                                    method)
                            elif which_type == 'tuple':
                                access = 'entity.get{}()'.format(method)
                            else:
                                raise RuntimeError(
                                    'Unexpected field type for XML export: ' +
                                    which_type)
                            if wantAttrs == ('xml_attribute'
                                             in syslx.patterns(f.attrs)):
                                if wantAttrs:
                                    w('serializeAttr("{}", {}{}, xsw);',
                                      jfname, access, extra)
                                else:
                                    # TODO: Why is 'index' bad? (NB: This was a debug hook, but the author forgot why.)
                                    assert jfname != 'index'
                                    w('serializeField("{}", {}{}, xsw);',
                                      jfname, access, extra)
                    w('xsw.writeEndElement();')

                with java.Method(w,
                                 '\npublic',
                                 'void',
                                 'serializeField',
                                 [('String', 'fieldname'),
                                  (modelpkg + '.' + tname + '.View', 'view'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'view != null && !view.isEmpty()'):
                        w('serialize(view, xsw, fieldname);')

                with java.Method(w,
                                 '\npublic',
                                 'void',
                                 'serializeField',
                                 [('String', 'fieldname'),
                                  (modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'entity != null'):
                        w('serialize(entity, xsw, fieldname);')

        def serialize(t, access, extra_args=None):
            with java.Method(
                    w,
                    '\nprivate',
                    'void',
                    'serialize',
                ([(t, 'value')] +
                 (extra_args or []) + [('XMLStreamWriter', 'xsw')]),
                    throws=['XMLStreamException']):
                w('xsw.writeCharacters({});', access)

        serialize('String', 'value')
        serialize('Boolean', 'value.toString()')
        serialize('Integer', 'value.toString()')
        serialize('Double', 'value.toString()')
        serialize('BigDecimal', 'value.toString()')
        serialize('UUID', 'value.toString()')
        serialize('DateTime', 'fmt.print(value)',
                  [('DateTimeFormatter', 'fmt')])
        serialize('LocalDate', 'iso8601Date.print(value)')

        def serializeField(t, access, extra_args=None):
            with java.Method(
                    w,
                    '\nprivate',
                    'void',
                    'serializeField',
                ([('String', 'fieldname'), (t, 'value')] +
                 (extra_args or []) + [('XMLStreamWriter', 'xsw')]),
                    throws=['XMLStreamException']):
                with java.If(w, 'value != null'):
                    w('xsw.writeStartElement(fieldname);')
                    w('serialize(value{}, xsw);',
                      ''.join(', ' + arg for (_, arg) in extra_args or []))
                    w('xsw.writeEndElement();')

            with java.Method(
                    w,
                    '\nprivate',
                    'void',
                    'serializeAttr',
                ([('String', 'fieldname'), (t, 'value')] +
                 (extra_args or []) + [('XMLStreamWriter', 'xsw')]),
                    throws=['XMLStreamException']):
                with java.If(w, 'value != null'):
                    w('xsw.writeAttribute(fieldname, {});', access)

        serializeField('String', 'value')
        serializeField('Boolean', 'value.toString()')
        serializeField('Integer', 'value.toString()')
        serializeField('Double', 'value.toString()')
        serializeField('BigDecimal', 'value.toString()')
        serializeField('UUID', 'value.toString()')
        serializeField('DateTime', 'fmt.print(value)',
                       [('DateTimeFormatter', 'fmt')])
        serializeField('LocalDate', 'iso8601Date.print(value)')

        with java.Method(w, '\nprivate final', 'BigDecimal', 'round',
                         [('BigDecimal', 'd'), ('int', 'scale')]):
            w('return d == null ? d : '
              'd.setScale(scale, java.math.RoundingMode.HALF_UP);')

        w('\nprivate final DateTimeFormatter iso8601Date = '
          'ISODateTimeFormat.date();')
        w('private final DateTimeFormatter iso8601DateTime = '
          'ISODateTimeFormat.dateTime();')
Esempio n. 19
0
def _infer_types(app):
    """Infer types of views and expressions from their bodies.

    Synthesize types for anonymous transforms.
    """

    for (vname, v) in app.views.iteritems():
        assert ((v.expr.WhichOneof('expr') == 'transform') ^
                ('abstract' in syslx.patterns(v.attrs))), '{}: {}'.format(
                    vname, v.expr)

        if v.ret_type.WhichOneof('type') is None:
            assert v.expr.type.WhichOneof('type')
            v.ret_type.CopyFrom(v.expr.type)

        nAnons = [0]

        def infer_expr_type(expr, top=True):
            which_expr = expr.WhichOneof('expr')

            if which_expr == 'transform':
                transform = expr.transform

                # Must recurse first
                for stmt in transform.stmt:
                    which_stmt = stmt.WhichOneof('stmt')
                    if which_stmt in ['assign', 'let']:
                        infer_expr_type(getattr(stmt, which_stmt).expr, False)

                if not top and not expr.type.WhichOneof('type'):
                    tname = 'AnonType_{}__'.format(nAnons[0])
                    nAnons[0] += 1

                    newt = app.types[tname].tuple

                    for stmt in transform.stmt:
                        which_stmt = stmt.WhichOneof('stmt')
                        if which_stmt == 'assign':
                            assign = stmt.assign
                            aexpr = assign.expr
                            assert aexpr.WhichOneof(
                                'expr') == 'transform', aexpr
                            ftype = aexpr.type
                            setof = ftype.WhichOneof('type') == 'set'
                            if setof:
                                ftype = ftype.set
                            assert ftype.WhichOneof('type') == 'type_ref'

                            t = sysl_pb2.Type()
                            tr = t.type_ref
                            tr.context.appname.CopyFrom(app.name)
                            tr.context.path.append(tname)
                            tr.ref.CopyFrom(ftype.type_ref.ref)

                            if setof:
                                t = sysl_pb2.Type(set=t)

                            newt.attr_defs[assign.name].CopyFrom(t)

                    tr = expr.type.set.type_ref
                    tr.context.appname.CopyFrom(app.name)
                    tr.ref.appname.CopyFrom(app.name)
                    tr.ref.path.append(tname)

            elif which_expr == 'relexpr':
                relexpr = expr.relexpr

                if relexpr.op == relexpr.RANK:
                    if not top and not expr.type.WhichOneof('type'):
                        raise RuntimeError(
                            "rank() type inference not implemented")
                        expr.type.CopyFrom(infer_expr_type(relexpr.target))
                        rank = expr.type.add()
                        rank.primitive = rank.INT

            return expr.type

        infer_expr_type(v.expr)
Esempio n. 20
0
        def visit_stmts(stmts, deactivate, last_parent_stmt):
            """Recursively visit a stmt list."""
            def block(last_stmt, block_stmts, fmt, *args):
                """Output a compound block."""
                write(fmt, *args)
                with write.indent():
                    return visit_stmts(block_stmts, deactivate, last_stmt)

            def block_with_end(last_stmt, block_stmts, fmt, *args):
                """Output a compound block, including the 'end' clause."""
                payload = block(last_stmt, block_stmts, fmt, *args)
                write('end')
                return payload

            payload = None

            for (i, stmt) in enumerate(stmts):
                last_stmt = last_parent_stmt and i == len(stmts) - 1
                if stmt.HasField('call'):
                    with write.indent():
                        payload = visit_endpoint(
                            app, syslx.fmt_app_name(stmt.call.target),
                            stmt.call.endpoint, uptos, app_patterns,
                            syslx.patterns(stmt.attrs)
                            | syslx.patterns(endpt.attrs), stmt, last_stmt
                            and deactivate)
                elif stmt.HasField('action'):
                    #write('{0} -> {0} : {1}', agent, r'\n'.join(textwrap.wrap(stmt.action.action, 40)))
                    write('{0} -> {0} : {1}', agent, stmt.action.action)
                elif stmt.HasField('cond'):
                    payload = block_with_end(last_stmt, stmt.cond.stmt,
                                             'opt {}', stmt.cond.test)
                elif stmt.HasField('loop'):
                    payload = block_with_end(
                        last_stmt, stmt.loop.stmt, 'loop {} {}',
                        stmt.loop.Mode.Name(stmt.loop.mode),
                        stmt.loop.criterion)
                elif stmt.HasField('loop_n'):
                    payload = block_with_end(last_stmt, stmt.loop_n.stmt,
                                             'loop {} times',
                                             stmt.loop_n.count)
                elif stmt.HasField('foreach'):
                    payload = block_with_end(last_stmt, stmt.foreach.stmt,
                                             'loop for each {}',
                                             stmt.foreach.collection)
                elif stmt.HasField('group'):
                    payload = block_with_end(last_stmt, stmt.group.stmt,
                                             'group {}', stmt.group.title)
                elif stmt.HasField('alt'):
                    prefix = 'alt'
                    for (j, choice) in enumerate(stmt.alt.choice):
                        last_alt_stmt = last_stmt and j == len(
                            stmt.alt.choice) - 1
                        payload = block(last_alt_stmt, choice.stmt, '{} {}',
                                        prefix, choice.cond)
                        prefix = 'else'
                    write('end')
                elif stmt.HasField('ret'):
                    rargs = []

                    for param in syslalgo.yield_ret_params(stmt.ret.payload):
                        if param != '...' and '.' in param:
                            (an, pn) = rex.split(r'\.', param)

                            rarg = format_args(an, pn)

                            if rarg:
                                rargs.append(rarg)
                        else:
                            rargs.append(param)

                    write('{}<--{} : {}', sender, agent,
                          ' | '.join(p for p in rargs))
                else:
                    raise Exception('No statement!')

            return payload
Esempio n. 21
0
    def visit_endpoint(from_app,
                       appname,
                       epname,
                       uptos,
                       sender_patterns,
                       sender_endpt_patterns=None,
                       stmt=None,
                       deactivate=None):
        """Recursively visit an endpoint."""
        if from_app:
            sender = var_name(syslx.fmt_app_name(from_app.name))
        else:
            sender = '['
        agent = var_name(appname)
        app = module.apps.get(appname)
        endpt = app.endpoints.get(epname)
        assert endpt

        def visit_stmts(stmts, deactivate, last_parent_stmt):
            """Recursively visit a stmt list."""
            def block(last_stmt, block_stmts, fmt, *args):
                """Output a compound block."""
                write(fmt, *args)
                with write.indent():
                    return visit_stmts(block_stmts, deactivate, last_stmt)

            def block_with_end(last_stmt, block_stmts, fmt, *args):
                """Output a compound block, including the 'end' clause."""
                payload = block(last_stmt, block_stmts, fmt, *args)
                write('end')
                return payload

            payload = None

            for (i, stmt) in enumerate(stmts):
                last_stmt = last_parent_stmt and i == len(stmts) - 1
                if stmt.HasField('call'):
                    with write.indent():
                        payload = visit_endpoint(
                            app, syslx.fmt_app_name(stmt.call.target),
                            stmt.call.endpoint, uptos, app_patterns,
                            syslx.patterns(stmt.attrs)
                            | syslx.patterns(endpt.attrs), stmt, last_stmt
                            and deactivate)
                elif stmt.HasField('action'):
                    #write('{0} -> {0} : {1}', agent, r'\n'.join(textwrap.wrap(stmt.action.action, 40)))
                    write('{0} -> {0} : {1}', agent, stmt.action.action)
                elif stmt.HasField('cond'):
                    payload = block_with_end(last_stmt, stmt.cond.stmt,
                                             'opt {}', stmt.cond.test)
                elif stmt.HasField('loop'):
                    payload = block_with_end(
                        last_stmt, stmt.loop.stmt, 'loop {} {}',
                        stmt.loop.Mode.Name(stmt.loop.mode),
                        stmt.loop.criterion)
                elif stmt.HasField('loop_n'):
                    payload = block_with_end(last_stmt, stmt.loop_n.stmt,
                                             'loop {} times',
                                             stmt.loop_n.count)
                elif stmt.HasField('foreach'):
                    payload = block_with_end(last_stmt, stmt.foreach.stmt,
                                             'loop for each {}',
                                             stmt.foreach.collection)
                elif stmt.HasField('group'):
                    payload = block_with_end(last_stmt, stmt.group.stmt,
                                             'group {}', stmt.group.title)
                elif stmt.HasField('alt'):
                    prefix = 'alt'
                    for (j, choice) in enumerate(stmt.alt.choice):
                        last_alt_stmt = last_stmt and j == len(
                            stmt.alt.choice) - 1
                        payload = block(last_alt_stmt, choice.stmt, '{} {}',
                                        prefix, choice.cond)
                        prefix = 'else'
                    write('end')
                elif stmt.HasField('ret'):
                    rargs = []

                    for param in syslalgo.yield_ret_params(stmt.ret.payload):
                        if param != '...' and '.' in param:
                            (an, pn) = rex.split(r'\.', param)

                            rarg = format_args(an, pn)

                            if rarg:
                                rargs.append(rarg)
                        else:
                            rargs.append(param)

                    write('{}<--{} : {}', sender, agent,
                          ' | '.join(p for p in rargs))
                else:
                    raise Exception('No statement!')

            return payload

        app_patterns = syslx.patterns(app.attrs)
        target_patterns = syslx.patterns(endpt.attrs)

        patterns = target_patterns

        human = 'human' in app_patterns
        human_sender = 'human' in sender_patterns
        cron = 'cron' in sender_patterns
        needs_int = not (human or human_sender or cron) and sender != agent
        label = re.sub(ur'^.*? -> ', u' ⬄ ', unicode(epname))

        cron = 'cron' in app_patterns

        if stmt:
            assert stmt.HasField('call')

            ptrns = ''
            if bool(sender_endpt_patterns) or bool(patterns):
                ptrns = u', '.join(sorted(sender_endpt_patterns)) + \
                    u' → ' + u', '.join(sorted(patterns))

            isoctrl = []

            for ctrl in endpt.attrs.keys():
                if 'iso_ctrl' in ctrl:
                    isoctrl.append(re.sub(r'iso_ctrl_(.*)_txt', r'\1', ctrl))

            epargs = []

            def format_args(an, pn):
                arg = '.'.join((an, pn))

                if arg:
                    conf = module.apps[an].types[pn].attrs[
                        'iso_conf'].s[:1].upper()
                    integ = module.apps[an].types[pn].attrs[
                        'iso_integ'].s[:1].upper()
                    isocolor = 'red' if 'R' in conf else 'green'
                    arg = '<color blue>' + arg + '</color>' + ' <<color ' + isocolor + '>' + \
                        (conf if conf else '?') + ', ' + \
                        (integ if integ else '?') + '</color>>'

                return arg

            for p in endpt.param:
                an = ' :: '.join(p.type.type_ref.ref.appname.part)
                pn = '.'.join(p.type.type_ref.ref.path)

                eparg = format_args(an, pn)

                if eparg:
                    epargs.append(eparg)

            label = params.epfmt(
                epname=label,
                human='human' if human else '',
                human_sender='human sender' if human_sender else '',
                needs_int='needs_int' if needs_int else '',
                args=' | '.join(e for e in epargs),
                #args=', '.join(p.name for p in stmt.call.arg),
                patterns=ptrns,
                controls=', '.join(i for i in sorted(isoctrl)),
                **diagutil.attr_fmt_vars(stmt.attrs)).replace('\n', r'\n')

        if not ((human and sender == '[') or cron):
            ep_patterns = syslx.patterns(endpt.attrs)

            icon = '<&timer> ' if 'cron' in ep_patterns else ''
            write('{}->{} : {}{}', sender, agent, icon, label)
            if log_integration and stmt:
                log_integration(app=from_app, stmt=stmt, patterns=patterns)

        rargs = []

        for param in syslalgo.yield_ret_params(
                syslalgo.return_payload(endpt.stmt)):
            if param != '...' and '.' in param:
                (an, pn) = rex.split(r'\.', param)

                rarg = format_args(an, pn)

                if rarg:
                    rargs.append(rarg)
            else:
                rargs.append(param)

        payload = ' | '.join(p for p in rargs)

        calling_self = from_app and syslx.fmt_app_name(
            from_app.name) == appname
        if not calling_self and not payload and deactivate:
            deactivate()

        if len(endpt.stmt):
            hit_blackbox = False
            for (upto, comment) in itertools.chain(uptos.iteritems(),
                                                   already_visited.keys()):
                # Compare the common prefix of the current endpt and upto.
                upto_parts = upto.split(' <- ')
                if [appname, epname][:len(upto_parts)] == upto_parts:
                    hit_blackbox = True
                    if payload:
                        write.activate(agent)
                        if comment is not None:
                            write('note over {}: {}', agent, comment
                                  or 'see below')
                    else:
                        if comment is not None:
                            write('note {}: {}',
                                  'left' if sender > agent else 'right',
                                  comment or 'see below')
                    if payload:
                        write('{}<--{} : {}', sender, agent, payload)
                        write.deactivate(agent)
                    break

            if not hit_blackbox:
                with write.activated(agent, human or cron) as deactivate:
                    # 'see above')
                    visiting = (appname + ' <- ' + epname, None)
                    already_visited[visiting] += 1
                    try:
                        return visit_stmts(endpt.stmt, deactivate, True)
                    finally:
                        already_visited[visiting] -= 1
                        if not already_visited[visiting]:
                            del already_visited[visiting]
Esempio n. 22
0
File: xsd.py Progetto: ANZ-bank/Sysl
    def build_relational_xsd():
        # top level element contains all entities for
        # relational schemas but will only contain the
        # root entity for hierarchical
        with xs('element', name=context.model_class):
            with xs('complexType'):
                with xs('sequence', minOccurs=1, maxOccurs=1):
                    # each "relation" is a list of things
                    for (tname, ft, t) in syslx.sorted_types(context):
                        if t.HasField('relation'):
                            xs('element/', name=tname + 'List', type=tname + 'List',
                               minOccurs=0)

            # build keys and key refs
            for (tname, ft, t) in syslx.sorted_types(context):
                if t.HasField('relation'):
                    pkey = datamodel.primary_key_params(t, context.module)
                    pkey_fields = {f for (_, f, _) in pkey}
                    has_content = False

                    def xsd_key_header(msg):
                        w('{}', '<!-- ' + msg.center(55) + ' -->')

                    if pkey:
                        if not has_content:
                            has_content = True
                            w()
                            w(xsd_separator)
                            xsd_key_header(tname + ' keys')

                        with xs('key', name='key_' + tname):
                            xs('selector/',
                               xpath='./{0}List/{0}'.format(tname))
                            for f in sorted(pkey_fields):
                                xs('field/', xpath=f)

                    for (i, (fname, _, type_info)) in enumerate(sorted(
                            datamodel.foreign_keys(t, context.module))):
                        if not has_content:
                            has_content = True
                            w()
                            w(xsd_separator)
                            xsd_key_header(tname + ' keyrefs')
                        elif pkey and i == 0:
                            xsd_key_header('keyrefs')
                        fk_type = type_info.parent_path
                        fk_field = type_info.field
                        with xs('keyref',
                                name='keyref_{}_{}'.format(tname, fname),
                                refer='key_' + fk_type):
                            xs('selector/',
                               xpath='./{0}List/{0}'.format(tname))
                            xs('field/', xpath=fname)
                    if has_content:
                        w(xsd_separator)
            w()

        w()
        # construct the entities
        for (tname, ft, t) in syslx.sorted_types(context):
            if t.HasField('relation'):
                with xs('complexType', name=tname + 'List'):
                    with xs('sequence', maxOccurs='unbounded'):
                        with xs('element', name=tname):
                            with xs('complexType'):
                                with xs('all'):
                                    for (fname, f) in sorted(
                                            t.relation.attr_defs.iteritems()):
                                        if 'xml_attribute' not in syslx.patterns(
                                                f.attrs):
                                            build_element(
                                                fname, f, False, False)

                                # attributes second
                                for (fname, f) in sorted(
                                        t.relation.attr_defs.iteritems()):
                                    if 'xml_attribute' in syslx.patterns(
                                            f.attrs):
                                        build_element(fname, f, False, True)
Esempio n. 23
0
def export_facade_class(context):
    model_name = syslx.fmt_app_name(context.wrapped_model.name)
    modelpkg = syslx.View(context.wrapped_model.attrs)['package'].s

    w = writer.Writer('java')

    java.Package(w, context.package)
    java.StandardImports(w)
    java.Import(w, modelpkg + '.' + model_name)

    w()
    with java.Class(w,
                    context.appname,
                    context.write_file,
                    package=context.package):
        with java.Ctor(w, '\npublic', context.appname,
                       [(model_name, 'model')]):
            w('this.model = model;')
            for (tname, _, _) in syslx.wrapped_facade_types(context):
                w('this.{}Facade = new {}Facade();',
                  java.safe(tname[:1].lower() + tname[1:]), tname)

        with java.Method(w, '\npublic', model_name, 'getModel'):
            w('return model;')

        java.SeparatorComment(w)

        for (tname, ft, t) in syslx.wrapped_facade_types(context):
            if t.HasField('relation'):
                pkey = datamodel.primary_key_params(t, context.module)
                pkey_fields = {f for (_, f, _) in pkey}
                param_defs = [(typ, jfname) for (typ, fname, jfname) in pkey
                              if 'autoinc' not in syslx.patterns(
                                  t.relation.attr_defs[fname].attrs)]
                params = ''.join(', ' + f for (_, f) in param_defs)
                param = ', '.join(f for (_, f) in param_defs)

                fkeys = {
                    java.name(fname): type_info
                    for (fname, _, type_info
                         ) in datamodel.foreign_keys(t, context.module)
                }

                inner_type = ('HashMap<Key, {}>'
                              if pkey else 'HashSet<{}>').format(tname)

                required = []
                for fname in sorted(ft.relation.attr_defs.keys()):
                    f = t.relation.attr_defs.get(fname)
                    if ('required' in syslx.patterns(f.attrs)
                            or 'required' in syslx.patterns(
                                ft.relation.attr_defs.get(fname).attrs)):
                        jfname = java.name(fname)
                        method = java.CamelCase(jfname)
                        (java_type, type_info,
                         _) = datamodel.typeref(f, context.module)
                        if java_type == 'Object':
                            datamodel.typeref(f, context.module)
                        required.append((fname, java_type))

                with java.Method(w, '\npublic', tname + 'Facade',
                                 'get' + tname):
                    w('return {}Facade;',
                      java.safe(tname[:1].lower() + tname[1:]))

                w()
                with java.Class(w, tname + 'Facade', context.write_file):
                    with java.Method(w, 'public',
                                     '{}.{}.Table'.format(modelpkg,
                                                          tname), 'table'):
                        w('return model.get{}Table();', tname, param)

                    w()
                    if param_defs or required:
                        with java.Method(w, 'public', 'Builder0', 'build'):
                            w('return new Builder0();')

                        keytypes = {f: kt for (kt, f) in param_defs}
                        keys = sorted(keytypes)
                        keyindices = {k: i for (i, k) in enumerate(keys)}

                        if len(keys) > 3:
                            # 4 perms yields 16 builders with 32 setters.
                            logging.error('OUCH! Too many primary key fields')
                            raise Exception('Too many primary key fields')
                        for perm in range(2**len(keys)):
                            bname = 'Builder' + str(perm)
                            w()
                            with java.Class(w, bname, context.write_file):
                                done = [
                                    k for (i, k) in enumerate(keys)
                                    if 2**i & perm
                                ]
                                remaining = [k for k in keys if k not in done]

                                with java.Ctor(w, '', bname, [(keytypes[k], k)
                                                              for k in done]):
                                    for k in done:
                                        w('this.{0} = {0};', k)
                                    if required and not remaining:
                                        w(
                                            'this._pending = {};',
                                            hex(2**len(required) -
                                                1).rstrip('L'))

                                for fname in remaining:
                                    f = t.relation.attr_defs[fname]
                                    jfname = java.name(fname)
                                    method = java.CamelCase(jfname)
                                    (java_type, type_info,
                                     _) = datamodel.typeref(f, context.module)
                                    next_bname = 'Builder{}'.format(
                                        perm | 2**keyindices[fname])
                                    w()

                                    if jfname in fkeys:
                                        fk_type = fkeys[jfname].parent_path
                                        fk_field = fkeys[jfname].field
                                        if f.type_ref.ref.path[-1:] == [fname]:
                                            method_suffix = fk_type
                                        else:
                                            method_suffix = method + 'From'
                                        with java.Method(
                                                w, 'public', next_bname,
                                                'with' + method_suffix,
                                            [(modelpkg + '.' + fk_type,
                                              'entity')]):
                                            w(
                                                '{} {} = entity == null ? null : entity.get{}();',
                                                java_type, jfname,
                                                java.CamelCase(fk_field))
                                            w(
                                                'return new {}({});',
                                                next_bname,
                                                ', '.join(k for k in keys
                                                          if k == fname
                                                          or k in done))
                                    else:
                                        with java.Method(
                                                w, 'public', next_bname,
                                                'with' + java.CamelCase(fname),
                                            [(keytypes[fname], fname)]):
                                            w(
                                                'return new {}({});',
                                                next_bname,
                                                ', '.join(k for k in keys
                                                          if k == fname
                                                          or k in done))

                                if not remaining:
                                    for (i, (r, rtype)) in enumerate(required):
                                        method = java.CamelCase(r)
                                        w()

                                        # TODO: jfname set in a previous loop??
                                        if jfname in fkeys:
                                            fk_type = fkeys[jfname].parent_path
                                            fk_field = fkeys[jfname].field
                                            if f.type_ref.ref.path[-1:] == [
                                                    fname
                                            ]:
                                                method = fk_type
                                            else:
                                                method += 'From'
                                            with java.Method(
                                                    w, 'public', bname,
                                                    'with' + method,
                                                [(modelpkg + '.' + fk_type,
                                                  java.mixedCase(fk_type))]):
                                                with java.If(
                                                        w,
                                                        '(_pending & {}) == 0',
                                                        hex(2**i)):
                                                    # TODO: More specific
                                                    # exception
                                                    w('throw new RuntimeException();'
                                                      )
                                                w('this.{0} = {0};',
                                                  java.mixedCase(fk_type))
                                                w('_pending &= ~{};',
                                                  hex(2**i))
                                                w('return this;')
                                        else:
                                            with java.Method(
                                                    w, 'public', bname,
                                                    'with' + method,
                                                [(rtype, r)]):
                                                with java.If(
                                                        w,
                                                        '(_pending & {}) == 0',
                                                        hex(2**i)):
                                                    # TODO: More specific
                                                    # exception
                                                    w('throw new RuntimeException();'
                                                      )
                                                w('this.{0} = {0};', r)
                                                w('_pending &= ~{};',
                                                  hex(2**i))
                                                w('return this;')

                                    with java.Method(w, '\npublic',
                                                     modelpkg + '.' + tname,
                                                     'insert'):
                                        if required:
                                            with java.If(w, '_pending != 0'):
                                                # TODO: More specific exception
                                                w('throw new RuntimeException();'
                                                  )
                                            w(
                                                u'{} result = table()._PRIVATE_insert({});',
                                                modelpkg + '.' + tname, param)
                                            for (r, rtype) in required:
                                                if jfname in fkeys:
                                                    fk_field = fkeys[
                                                        jfname].field
                                                    w('result.set{}({});',
                                                      fk_type,
                                                      java.mixedCase(fk_type))
                                                else:
                                                    w('result.set{}({});',
                                                      java.CamelCase(r), r)
                                            w('return result;')
                                        else:
                                            w(
                                                u'return table()._PRIVATE_insert({});',
                                                param)

                                if done:
                                    w()
                                    w('// primary key')
                                    for d in done:
                                        w('private final {} {};', keytypes[d],
                                          d)

                                if required and not remaining:
                                    w()
                                    w('// required fields')
                                    for (r, rtype) in required:
                                        if jfname in fkeys:
                                            fk_type = fkeys[jfname].parent_path
                                            fk_field = fkeys[jfname].field
                                            w('private {} {};',
                                              modelpkg + '.' + fk_type,
                                              java.mixedCase(fk_type))
                                        else:
                                            w('private {} {};', rtype, r)
                                    w()
                                    w('private int _pending;')
                    else:
                        with java.Method(w, 'public', modelpkg + '.' + tname,
                                         'insert'):
                            w('{} result = table()._PRIVATE_insert();',
                              modelpkg + '.' + tname)
                            w('return result;')

                java.SeparatorComment(w)

        for (tname, _, t) in syslx.wrapped_facade_types(context):
            if t.HasField('relation'):
                w('private final {}Facade {}Facade;', tname,
                  java.safe(tname[:1].lower() + tname[1:]))

        w()
        w('private final {}.{} model;', modelpkg, model_name)
        w()
Esempio n. 24
0
    def build_relational_xsd():
        # top level element contains all entities for
        # relational schemas but will only contain the
        # root entity for hierarchical
        with xs('element', name=context.model_class):
            with xs('complexType'):
                with xs('sequence', minOccurs=1, maxOccurs=1):
                    # each "relation" is a list of things
                    for (tname, ft, t) in syslx.sorted_types(context):
                        if t.HasField('relation'):
                            xs('element/',
                               name=tname + 'List',
                               type=tname + 'List',
                               minOccurs=0)

            # build keys and key refs
            for (tname, ft, t) in syslx.sorted_types(context):
                if t.HasField('relation'):
                    pkey = datamodel.primary_key_params(t, context.module)
                    pkey_fields = {f for (_, f, _) in pkey}
                    has_content = False

                    def xsd_key_header(msg):
                        w('{}', '<!-- ' + msg.center(55) + ' -->')

                    if pkey:
                        if not has_content:
                            has_content = True
                            w()
                            w(xsd_separator)
                            xsd_key_header(tname + ' keys')

                        with xs('key', name='key_' + tname):
                            xs('selector/',
                               xpath='./{0}List/{0}'.format(tname))
                            for f in sorted(pkey_fields):
                                xs('field/', xpath=f)

                    for (i, (fname, _, type_info)) in enumerate(
                            sorted(datamodel.foreign_keys(t, context.module))):
                        if not has_content:
                            has_content = True
                            w()
                            w(xsd_separator)
                            xsd_key_header(tname + ' keyrefs')
                        elif pkey and i == 0:
                            xsd_key_header('keyrefs')
                        fk_type = type_info.parent_path
                        fk_field = type_info.field
                        with xs('keyref',
                                name='keyref_{}_{}'.format(tname, fname),
                                refer='key_' + fk_type):
                            xs('selector/',
                               xpath='./{0}List/{0}'.format(tname))
                            xs('field/', xpath=fname)
                    if has_content:
                        w(xsd_separator)
            w()

        w()
        # construct the entities
        for (tname, ft, t) in syslx.sorted_types(context):
            if t.HasField('relation'):
                with xs('complexType', name=tname + 'List'):
                    with xs('sequence', maxOccurs='unbounded'):
                        with xs('element', name=tname):
                            with xs('complexType'):
                                with xs('all'):
                                    for (fname, f) in sorted(
                                            t.relation.attr_defs.iteritems()):
                                        if 'xml_attribute' not in syslx.patterns(
                                                f.attrs):
                                            build_element(
                                                fname, f, False, False)

                                # attributes second
                                for (fname, f) in sorted(
                                        t.relation.attr_defs.iteritems()):
                                    if 'xml_attribute' in syslx.patterns(
                                            f.attrs):
                                        build_element(fname, f, False, True)
Esempio n. 25
0
def _infer_types(app):
    """Infer types of views and expressions from their bodies.

    Synthesize types for anonymous transforms.
    """

    for (vname, v) in app.views.iteritems():
        assert (
            (v.expr.WhichOneof('expr') == 'transform') ^
            ('abstract' in syslx.patterns(v.attrs))
        ), '{}: {}'.format(vname, v.expr)

        if v.ret_type.WhichOneof('type') is None:
            assert v.expr.type.WhichOneof('type')
            v.ret_type.CopyFrom(v.expr.type)

        nAnons = [0]

        def infer_expr_type(expr, top=True):
            which_expr = expr.WhichOneof('expr')

            if which_expr == 'transform':
                transform = expr.transform

                # Must recurse first
                for stmt in transform.stmt:
                    which_stmt = stmt.WhichOneof('stmt')
                    if which_stmt in ['assign', 'let']:
                        infer_expr_type(getattr(stmt, which_stmt).expr, False)

                if not top and not expr.type.WhichOneof('type'):
                    tname = 'AnonType_{}__'.format(nAnons[0])
                    nAnons[0] += 1

                    newt = app.types[tname].tuple

                    for stmt in transform.stmt:
                        which_stmt = stmt.WhichOneof('stmt')
                        if which_stmt == 'assign':
                            assign = stmt.assign
                            aexpr = assign.expr
                            assert aexpr.WhichOneof(
                                'expr') == 'transform', aexpr
                            ftype = aexpr.type
                            setof = ftype.WhichOneof('type') == 'set'
                            if setof:
                                ftype = ftype.set
                            assert ftype.WhichOneof('type') == 'type_ref'

                            t = sysl_pb2.Type()
                            tr = t.type_ref
                            tr.context.appname.CopyFrom(app.name)
                            tr.context.path.append(tname)
                            tr.ref.CopyFrom(ftype.type_ref.ref)

                            if setof:
                                t = sysl_pb2.Type(set=t)

                            newt.attr_defs[assign.name].CopyFrom(t)

                    tr = expr.type.set.type_ref
                    tr.context.appname.CopyFrom(app.name)
                    tr.ref.appname.CopyFrom(app.name)
                    tr.ref.path.append(tname)

            elif which_expr == 'relexpr':
                relexpr = expr.relexpr

                if relexpr.op == relexpr.RANK:
                    if not top and not expr.type.WhichOneof('type'):
                        raise RuntimeError(
                            "rank() type inference not implemented")
                        expr.type.CopyFrom(infer_expr_type(relexpr.target))
                        rank = expr.type.add()
                        rank.primitive = rank.INT

            return expr.type

        infer_expr_type(v.expr)
Esempio n. 26
0
def serializer(context):
    (app, module, package, model_class, write_file, _, _) = context

    facade = bool(context.wrapped_model)

    w = writer.Writer('java')

    java.Package(w, package)

    java.StandardImports(w)

    java.Import(w, 'java.text.ParseException')
    w.head()
    java.Import(w, 'javax.xml.stream.XMLStreamException')
    java.Import(w, 'javax.xml.stream.XMLStreamWriter')
    w.head()
    java.Import(w, 'org.joda.time.format.DateTimeFormatter')
    java.Import(w, 'org.joda.time.format.ISODateTimeFormat')

    if facade:
        model_name = syslx.fmt_app_name(context.wrapped_model.name)
        modelpkg = syslx.View(context.wrapped_model.attrs)['package'].s
        w.head()
        java.Import(w, modelpkg + '.*')
    else:
        modelpkg = package

    with java.Class(w, '\n{}XmlSerializer'.format(model_class), write_file,
                    package=package):
        with java.Method(w, '\npublic', 'void', 'serialize',
                         [(model_class, 'facade' if facade else 'model'),
                          ('XMLStreamWriter', 'xsw')],
                         throws=['XMLStreamException']):
            if facade:
                w('{} model = facade.getModel();', model_name)

            w('xsw.writeStartElement("{}");', model_class)
            for (tname, ft, t) in syslx.sorted_types(context):
                if t.WhichOneof('type') == 'relation':
                    w('serialize(model.get{0}Table(), xsw, "{0}");', tname)
            w('xsw.writeEndElement();')

        for (tname, ft, t) in syslx.sorted_types(context):
            java.SeparatorComment(w)

            if t.WhichOneof('type') in ['relation', 'tuple']:
                with java.Method(w, '\npublic', 'void', 'serialize',
                                 [(modelpkg + '.' + tname + '.View', 'view'),
                                  ('XMLStreamWriter', 'xsw'),
                                  ('String', 'tag')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'view == null || view.isEmpty()'):
                        w('return;')
                    if t.WhichOneof('type') == 'relation':
                        w('xsw.writeStartElement("{}List");', tname)
                    order = [o.s for o in syslx.View(
                        t.attrs)['xml_order'].a.elt]
                    if order:
                        order_logic = []
                        for o in order:
                            order_logic.append(
                                '            i = io.sysl.ExprHelper.doCompare'
                                '(a.get{0}(), b.get{0}());\n'
                                '            if (i != 0) return i;\n'.format(java.CamelCase(o)))
                        order_by = (
                            '.orderBy(\n'
                            '    new java.util.Comparator<{0}> () {{\n'
                            '        @Override\n'
                            '        public int compare({0} a, {0} b) {{\n'
                            '            int i;\n'
                            '{1}'
                            '            return 0;\n'
                            '        }}\n'
                            '    }})\n').format(tname, ''.join(order_logic))
                    else:
                        order_by = ''

                    with java.For(w, '{} item : view{}',
                                  modelpkg + '.' + tname, order_by):
                        w('serialize(item, xsw, tag);', tname)
                    if t.WhichOneof('type') == 'relation':
                        w('xsw.writeEndElement();')

                with java.Method(w, '\npublic', 'void', 'serialize',
                                 [(modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    w('serialize(entity, xsw, "{}");', tname)

                with java.Method(w, '\npublic', 'void', 'serialize',
                                 [(modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw'),
                                  ('String', 'tag')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'entity == null'):
                        w('return;')
                    w('xsw.writeStartElement(tag);', tname)
                    for wantAttrs in [True, False]:
                        for (fname, f) in datamodel.sorted_fields(t):
                            jfname = java.name(fname)
                            method = java.CamelCase(jfname)
                            tref = datamodel.typeref(f, module)
                            type_ = tref[2]
                            if not type_:
                                continue
                            extra = ''
                            which_type = type_.WhichOneof('type')
                            if which_type == 'primitive':
                                extra = XML_GEN_MAP[type_.primitive]
                                if type_.primitive == type_.DECIMAL:
                                    for c in type_.constraint:
                                        if c.scale:
                                            access = 'round(entity.get{}(), {})'.format(
                                                method, c.scale)
                                            break
                                    else:
                                        access = 'round(entity.get{}(), 0)'.format(
                                            method)
                                else:
                                    access = 'entity.get{}()'.format(method)
                            elif which_type == 'enum':
                                access = 'entity.get{}().getValue()'.format(method)
                            elif which_type == 'tuple':
                                access = 'entity.get{}()'.format(method)
                            else:
                                raise RuntimeError(
                                    'Unexpected field type for XML export: ' + which_type)
                            if wantAttrs == (
                                    'xml_attribute' in syslx.patterns(f.attrs)):
                                if wantAttrs:
                                    w('serializeAttr("{}", {}{}, xsw);',
                                      jfname, access, extra)
                                else:
                                    # TODO: Why is 'index' bad? (NB: This was a debug hook, but the author forgot why.)
                                    assert jfname != 'index'
                                    w('serializeField("{}", {}{}, xsw);',
                                      jfname, access, extra)
                    w('xsw.writeEndElement();')

                with java.Method(w, '\npublic', 'void', 'serializeField',
                                 [('String', 'fieldname'),
                                  (modelpkg + '.' + tname + '.View', 'view'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'view != null && !view.isEmpty()'):
                        w('serialize(view, xsw, fieldname);')

                with java.Method(w, '\npublic', 'void', 'serializeField',
                                 [('String', 'fieldname'), (modelpkg + '.' + tname, 'entity'),
                                  ('XMLStreamWriter', 'xsw')],
                                 throws=['XMLStreamException']):
                    with java.If(w, 'entity != null'):
                        w('serialize(entity, xsw, fieldname);')

        def serialize(t, access, extra_args=None):
            with java.Method(w, '\nprivate', 'void', 'serialize',
                             ([(t, 'value')] + (extra_args or []) +
                              [('XMLStreamWriter', 'xsw')]),
                             throws=['XMLStreamException']):
                w('xsw.writeCharacters({});', access)

        serialize('String', 'value')
        serialize('Boolean', 'value.toString()')
        serialize('Integer', 'value.toString()')
        serialize('Double', 'value.toString()')
        serialize('BigDecimal', 'value.toString()')
        serialize('UUID', 'value.toString()')
        serialize('DateTime', 'fmt.print(value)',
                  [('DateTimeFormatter', 'fmt')])
        serialize('LocalDate', 'iso8601Date.print(value)')

        def serializeField(t, access, extra_args=None):
            with java.Method(w, '\nprivate', 'void', 'serializeField',
                             ([('String', 'fieldname'), (t, 'value')] + (extra_args or []) +
                              [('XMLStreamWriter', 'xsw')]),
                             throws=['XMLStreamException']):
                with java.If(w, 'value != null'):
                    w('xsw.writeStartElement(fieldname);')
                    w('serialize(value{}, xsw);',
                      ''.join(', ' + arg for (_, arg) in extra_args or []))
                    w('xsw.writeEndElement();')

            with java.Method(w, '\nprivate', 'void', 'serializeAttr',
                             ([('String', 'fieldname'), (t, 'value')] + (extra_args or []) +
                              [('XMLStreamWriter', 'xsw')]),
                             throws=['XMLStreamException']):
                with java.If(w, 'value != null'):
                    w('xsw.writeAttribute(fieldname, {});', access)

        serializeField('String', 'value')
        serializeField('Boolean', 'value.toString()')
        serializeField('Integer', 'value.toString()')
        serializeField('Double', 'value.toString()')
        serializeField('BigDecimal', 'value.toString()')
        serializeField('UUID', 'value.toString()')
        serializeField('DateTime', 'fmt.print(value)',
                       [('DateTimeFormatter', 'fmt')])
        serializeField('LocalDate', 'iso8601Date.print(value)')

        with java.Method(w, '\nprivate final', 'BigDecimal', 'round',
                         [('BigDecimal', 'd'), ('int', 'scale')]):
            w('return d == null ? d : '
              'd.setScale(scale, java.math.RoundingMode.HALF_UP);')

        w('\nprivate final DateTimeFormatter iso8601Date = '
          'ISODateTimeFormat.date();')
        w('private final DateTimeFormatter iso8601DateTime = '
          'ISODateTimeFormat.dateTime();')