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)
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
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)))
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)))
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
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
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
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
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
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())
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())
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
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
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 '')
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
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]
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();')
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)
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
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]
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)
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()
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)
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)
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();')