def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") if self.options.namespace: namespace = self.options.namespace else: raise builder_base.BuilderException( "You need to provide a namespace!") cppFilter = { 'camelcase': filter_lower, 'camelCase': filter.variableName, 'CamelCase': filter.typeName, 'CAMELCASE': filter.enumElement, } template = self.template('templates/cpp_caller.tpl', filter=cppFilter) # Bool has a special status because its primitive but user generated # and the only not numerical type components = self.tree.components substitutions = { 'components': components, 'events': self.tree.events, 'namespace': namespace } file = os.path.join(self.options.outpath, 'caller.hpp') self.write(file, template.render(substitutions))
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") if not self.options.container or self.options.container not in self.tree.containers: raise builder_base.BuilderException( "Please specify a valid container!") if self.options.namespace: namespace = self.options.namespace else: raise builder_base.BuilderException( "You need to provide a namespace!") cppFilter = { 'camelcase': filter_lower, 'camelCase': filter.variableName, 'CamelCase': filter.typeName, 'CAMELCASE': filter.enumElement, } container = self.tree.containers[self.options.container] components = [] for component in container.components: components.append(component.flattened()) # resumable function information resumableActions = 0 resumableActionsWithPayload = 0 for component in components: for action in component.actions: if action.call == "resumable": resumableActions += 1 if action.parameterType is not None: resumableActionsWithPayload += 1 substitutions = { 'resumables': resumableActions, 'resumablePayloads': resumableActionsWithPayload, 'components': components, 'events': self.tree.events, 'container': container, 'eventSubscriptions': container.subscriptions, 'namespace': namespace } file = os.path.join(self.options.outpath, 'postman.hpp') self.write( file, self.template('templates/postman.hpp.tpl', filter=cppFilter).render(substitutions) + "\n") file = os.path.join(self.options.outpath, 'postman.cpp') self.write( file, self.template('templates/postman.cpp.tpl', filter=cppFilter).render(substitutions) + "\n")
def generate(self): # check the commandline options if self.options.outpath: source_path = self.options.outpath header_path = self.options.outpath elif self.options.source_path and self.options.header_path: source_path = self.options.source_path header_path = self.options.header_path else: raise builder_base.BuilderException( "You need to provide an output path!") if self.options.system_include_path: includeDirective = '<%s>' % os.path.join( self.options.system_include_path, 'packets.hpp') elif self.options.quote_include_path: includeDirective = '"%s"' % os.path.join( self.options.system_include_path, 'packets.hpp') else: includeDirective = '"%s"' % 'packets.hpp' if self.options.namespace: namespace = self.options.namespace else: raise builder_base.BuilderException( "You need to provide a namespace!") cppFilter = { 'enumElement': filter.enumElement, 'enumElementStrong': filter.typeName, 'variableName': filter.variableName, 'typeName': filter.typeName, 'subtype': filter_subtype, 'generateConstructor': filter_constructor, 'generateArrayCopyCode': filter_array_constructor, 'generateInitializationList': filter_initialization_list, 'isConstexprConstructor': filter_constexpr_constructor } template_header = self.template('templates/robot_packets.hpp.tpl', filter=cppFilter) template_source = self.template('templates/robot_packets.cpp.tpl', filter=cppFilter) substitutions = { 'components': self.tree.components, 'actions': self.tree.components.actions, 'events': self.tree.events, 'packets': self.tree.types, 'includeDirective': includeDirective, 'namespace': namespace } file = os.path.join(header_path, 'packets.hpp') self.write(file, template_header.render(substitutions) + "\n") file = os.path.join(source_path, 'packets.cpp') self.write(file, template_source.render(substitutions) + "\n")
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") javaFilter = { 'enumElement': filter.enumElement, 'typeName': filter.typeName, 'typeObjectName': filter.typeObjectName, 'variableName': filter.variableName, 'inStringDescription': filter.inStringDescription, } template = self.template('templates/java_meta_communication.tpl', filter=javaFilter) # Bool has a special status because its primitive but user generated # and the only not numerical type components = self.tree.components primitives = sorted(filter.PRIMITIVES.values()) substitutions = { 'package': self.options.package, 'components': components, } file = os.path.join(self.options.outpath, 'MetaCommunication.java') self.write(file, template.render(substitutions))
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") javaFilter = { 'enumElement': filter.enumElement, 'enumElementStrong': filter.typeName, 'typeName': filter.typeName, 'typeObjectName': filter.typeObjectName, 'variableName': filter.variableName, 'fromBufferMethod': fromBufferMethod, 'toBufferMethod': toBufferMethod, 'toBufferMethodStructAccess': toBufferMethodStructAccess, } template = self.template('templates/java_packets.tpl', filter=javaFilter) # Bool has a special status because its primitive but user generated # and the only not numerical type packets = self.tree.types packets.remove('Bool') primitives = sorted(filter.PRIMITIVES.values()) substitutions = { 'package': self.options.package, 'packets': packets, 'primitives': primitives, } file = os.path.join(self.options.outpath, 'Packets.java') self.write(file, template.render(substitutions))
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") if not self.options.container or self.options.container not in self.tree.container: raise builder_base.BuilderException( "Please specifiy a vaild container!") cppFilter = { 'camelcase': filter_lower, 'camelCase': filter.variableName, 'CamelCase': filter.typeName, 'CAMELCASE': filter.enumElement, } container = self.tree.container[self.options.container] components = [] for component in container.components: components.append(component.flattened()) substitutions = { 'components': components, 'events': self.tree.events, 'container': container, 'eventSubscriptions': container.subscriptions, } file = os.path.join(self.options.outpath, 'postman.hpp') self.write( file, self.template('templates/postman.hpp.tpl', filter=cppFilter).render(substitutions) + "\n") file = os.path.join(self.options.outpath, 'postman.cpp') self.write( file, self.template('templates/postman.cpp.tpl', filter=cppFilter).render(substitutions) + "\n")
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException( "You need to provide an output path!") if self.options.namespace: namespace = self.options.namespace else: raise builder_base.BuilderException( "You need to provide a namespace!") cppFilter = { 'enumElement': filter.enumElement, 'enumElementStrong': filter.typeName, 'enumValue': filter.toHexValue, } template = self.template('templates/robot_identifier.tpl', filter=cppFilter) components = [] for component in self.tree.components.iter(abstract=False): components.append(component.flattened()) substitutions = { 'domains': self.tree.domains, 'containers': self.tree.containers, 'components': components, 'actions': self.tree.components.actions, 'events': self.tree.events, 'namespace': namespace } if os.path.splitext(self.options.outpath)[1] == '': file = os.path.join(self.options.outpath, 'identifier.hpp') else: file = self.options.outpath self.write(file, template.render(substitutions) + "\n")
def find_includes(self, file, include_path): """ Find include directives in an XML file """ includeExpression = re.compile(r'<include>(\S+)</include>', re.M) files = [] line_count = 0 for line in open(file).readlines(): line_count = line_count + 1 match = includeExpression.search(line) if match: try: filename = Parser.find_include_file( match.group(1), os.path.abspath(file), self.include_paths, str(line_count)) except ParserException as e: raise builder_base.BuilderException(e.message) files.append(filename) return files
def generate_xml_include_vertices(self, path, filename, label_path): """ Generates the dependency graph edges for the xml file """ max_stack_size = 40 # some precaution, because we are not detecting dependency loops stack = [filename] edges = [] while stack: nextFile = stack.pop() files = self.find_includes(os.path.join(path, nextFile), path) for file in files: a = os.path.relpath(os.path.join(path, nextFile), label_path) b = os.path.relpath(file, label_path) if (a, b) not in edges: edges.append((a, b)) if len(stack) < max_stack_size: stack.append(file) else: raise builder_base.BuilderException("Too many recoursions. You might have an include loop.") return edges
def generate(self): # check the commandline options if self.options.outpath: outpath = self.options.outpath else: raise builder_base.BuilderException("You need to provide an output path!") path, filename = os.path.split(os.path.abspath(self.xmlfile)) if self.options.label_path: label_path = os.path.abspath(self.options.label_path) else: label_path = path template = self.template('templates/include_graph.dot.tpl') edges = self.generate_xml_include_vertices(path, filename, label_path) substitutions = {'edges': edges, 'label_path': label_path} filename = os.path.basename(os.path.abspath(self.xmlfile)) file = os.path.join(outpath, filename[:-4] + '_include_graph.dot') self.write(file, template.render(substitutions) + "\n")
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException("You need to provide an output path!") javaFilter = { 'enumElement': filter.enumElement, 'typeObjectName': filter.typeObjectName, } template = self.template('templates/java_generator.tpl', filter=javaFilter) substitutions = { 'package' : self.options.package, 'domains': self.tree.domains, 'components': self.tree.components, 'actions': self.tree.components.actions, 'events': self.tree.events, } file = os.path.join(self.options.outpath, 'Generator.java') self.write(file, template.render(substitutions))
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException("You need to provide an output path!") template = self.template('templates/robot_identifier.tpl') components = [] for component in self.tree.components.iter(abstract=False): components.append(component.flattened()) substitutions = { 'components': components, 'actions': self.tree.components.actions, 'events': self.tree.events } if os.path.splitext(self.options.outpath)[1] == '': file = os.path.join(self.options.outpath, 'identifier.hpp') else: file = self.options.outpath self.write(file, template.render(substitutions) + "\n")
def generate(self): # check the commandline options if not self.options.outpath: raise builder_base.BuilderException("You need to provide an output path!") # Initialise unit.set(uscale=7) text.set(mode="latex") text.preamble(r"\usepackage{helvet}") text.preamble(r"\renewcommand*\familydefault{\sfdefault}") text.preamble(r"\normalfont") c = canvas.canvas() ### Object to draw eventArrowsSource = [] eventCirclesSource = [] eventTextSource = [] eventCirclesSinkless = [] eventCirclesSourcless = [] eventArrowsSink = [] eventCirclesSink = [] eventTextSink = [] actionArrows = [] actionText = [] ### Text Attributes self.textattrs = [text.halign.center, text.vshift.middlezero] self.textcontainerattrs = [text.halign.left, text.vshift.middlezero] self.texteventattrs = [text.halign.left, text.vshift(-0.6)] self.texteventrotattrs = [text.halign.left, text.vshift(-0.6), trafo.rotate(90), color.rgb.red] self.texteventsubscribedrotattrs = [text.halign.left, text.vshift(-0.6), trafo.rotate(90), color.rgb.blue] self.textactionrotattrs = [text.halign.left, text.vshift(-0.6), trafo.rotate(90), color.rgb(0.0, 0.5, 0.1)] # raster for design debug = False if debug: for x in np.arange(0, 20, 0.05): c.stroke(path.line(x, 10, x, 0), [style.linewidth.thin, color.gray(0.8)]) for y in np.arange(0, 10, 0.05): c.stroke(path.line(0, y, 20, y), [style.linewidth.thin, color.gray(0.8)]) for x in np.arange(0, 20, 0.5): c.stroke(path.line(x, 10, x, 0), [style.linewidth.thin, color.gray(0.5)]) for y in np.arange(0, 10, 0.5): c.stroke(path.line(0, y, 20, y), [style.linewidth.thin, color.gray(0.5)]) # Sorted events # Sort events by publishing component. Makes graph more structured. self.eventsSorted = [] print("Analysing containers:") for container in self.tree.containers: print(" * " + container.name) print("Done. Creating graph") for container in self.tree.containers: if container.name is None: continue if self.options.skipList is not None and container.name in self.options.skipList: continue for component in container.components: # include actions from abstract component component = component.flattened() for event in component.events.publish: # add only once if not (event in self.eventsSorted): self.eventsSorted.append(event) # Add sourceless events to the end for event in self.tree.events: if not (event in self.eventsSorted): self.eventsSorted.append(event) # Draw light gray horizontal lines for all events graph_width = self.get_graph_width(self.tree) + 2.1 for event in self.tree.events: event_y = self.get_y(event) c.stroke(path.line(0, event_y, graph_width, event_y), [style.linewidth.THick, color.grey(0.90)]) # Draw Id and name of event A = text.text(0, event_y, r"\bf \texttt{[0x%02x]} %s" % (event.id, event.name), self.texteventattrs) c.insert(A) # Draw type of Event if event.type is not None: A = text.text(1.1, event_y, r"%s" % (event.type.name), self.texteventattrs) c.insert(A) # Legend A = text.text( 0, 8.1, r"\textbf{%s}" % ("Id"), self.texteventattrs) c.insert(A) A = text.text(0.175, 8.1, r"\textbf{%s}" % ("Name"), self.texteventattrs) c.insert(A) A = text.text(1.1, 8.1, r"\textbf{%s}" % ("Type"), self.texteventattrs) c.insert(A) sinklessDict = dict() sourcelessDict = dict() # Write sink and sourceless events for event in self.tree.events: sourceless = True sinkless = True for component in self.tree.components: # include actions from abstract component component = component.flattened() if self.options.skipList is not None and component.name in self.options.skipList: continue for event_cmp in component.events.publish: if event_cmp == event: sourceless = False for event_cmp in component.events.subscribe: if event_cmp == event: sinkless = False if sourceless: A = text.text(1.8, self.get_y(event), r"\bf sourceless", self.texteventattrs) c.insert(A) sourcelessDict[event.name] = sourceless if sinkless: A = text.text(2.1, self.get_y(event), r"\bf sinkless", self.texteventattrs) c.insert(A) sinklessDict[event.name] = sinkless # Empty directories to find out from where to where a thick line # for events must be drawn. eventsLeft = SingleAssignDictionary('EventLeft') eventsRight = dict() # Write what was skipped c.insert(text.text(1, 9.8, r"\bf System Design generated from base file", self.textattrs)) c.insert(text.text(1, 9.7, r"\bf %s" % self.xmlfile.replace('_', '\_'), self.textattrs)) c.insert(text.text(1, 9.5, r"\bf Skipped containers:", self.textattrs)) y = 9.40 if self.options.skipList is not None: for s in self.options.skipList: A = text.text(1, y, r"\bf %s" % s, self.textattrs) c.insert(A) y = y - .1 # Draw containers at the top container_x = 2.5 for container in self.tree.containers: # skip containers that are requested to skip if self.options.skipList is not None and container.name in self.options.skipList: continue A = text.text(container_x + 0.15, 9.90, r"\bf %s" % container, self.textcontainerattrs) c.draw(path.rect(container_x + 0.05, 9.65, self.get_container_width(container), 0.30), [deco.stroked(), deco.filled([color.grey(0.85)])]) c.insert(A) component_x = container_x container_x = container_x + self.get_container_width(container) + 0.1 for component in container.components: # include actions from abstract component component = component.flattened() # A = text.text(0, event_y, r"\bf \texttt{[0x%02x]} %s" % (event.id, event.name), self.texteventattrs) A = text.text(component_x + self.get_component_width(component)/2 + 0.1, 9.8, r"\bf \texttt{[0x%02x]} %s" % (component.id, component.name), self.textattrs) c.draw(path.rect(component_x + 0.1, 9.75, self.get_component_width(component), 0.10), [deco.stroked(), deco.filled([color.grey(0.65)])]) c.insert(A) event_x = component_x + 0.15 component_x = component_x + self.get_component_width(component) + 0.1 # Draw vertical lines for published events for event in component.events.publish: eventArrowsSource.append(path.line(event_x, 9.75, event_x, self.get_y(event))) eventCirclesSource.append([event_x, 9.75]) if sinklessDict[event.name]: eventCirclesSinkless.append([event_x, self.get_y(event)]) # write name of event A = text.text(event_x, 8.1, r"\bf \texttt{[0x%02x]} %s" % (event.id, event.name), self.texteventrotattrs) c.insert(A) # Store most left position try: eventsLeft[event.name] = event_x except: pass # this could be the most right position eventsRight[event.name] = event_x event_x = event_x + 0.1 for event in component.events.subscribe: eventArrowsSink.append(path.line(event_x, self.get_y(event), event_x, 9.75)) if sourcelessDict[event.name]: eventCirclesSourcless.append([event_x, self.get_y(event)]) else: eventCirclesSink.append([event_x, self.get_y(event)]) A = text.text(event_x, 8.1, r"\bf \texttt{[0x%02x]} %s" % (event.id, event.name), self.texteventsubscribedrotattrs) c.insert(A) # Store most left position try: eventsLeft[event.name] = event_x except: pass eventsRight[event.name] = event_x event_x = event_x + 0.1 ### Draw actions if selected if self.options.actions: action_x = event_x for action in component.actions: c.stroke(path.line(action_x, 8.05, action_x, 9.75), [style.linewidth.THick, color.rgb(0.0, 0.5, 0.1), deco.earrow([deco.stroked([color.rgb(0.0, 0.5, 0.1), style.linejoin.round]), deco.filled([color.rgb(0.0, 0.5, 0.1)])], size=0.05)]) A = text.text(action_x, 8.1, r"\bf %s" % action.name, self.textactionrotattrs) c.insert(A) action_x = action_x + 0.1 ### Now we know from where to where to draw the thick lines # horizontal lines for events # eventsLeft = SingleAssignDictionary('EventLeft') # eventsRight = SingleAssignDictionary('EventRight') for event in self.tree.events: event_y = self.get_y(event) try: event_x_left = eventsLeft[event.name] event_x_right = eventsRight[event.name] c.stroke(path.line(event_x_left, event_y, event_x_right, event_y), [style.linewidth.THick, color.grey(0.40)]) except: pass ### Draw everything in the right order for p in eventArrowsSource: c.stroke(p, [style.linewidth.THick, color.rgb.red, deco.earrow([deco.stroked([color.rgb.red, style.linejoin.round]), deco.filled([color.rgb.red])], size=0.05)]) for p in eventArrowsSink: c.stroke(p, [style.linewidth.THick, color.rgb.blue, deco.earrow([deco.stroked([color.rgb.blue, style.linejoin.round]), deco.filled([color.rgb.blue])], size=0.05)]) for x, y in eventCirclesSource: c.fill(path.circle(x, y, 0.02), [color.rgb.red]) for x, y in eventCirclesSink: c.fill(path.circle(x, y, 0.02), [color.rgb.blue]) for x, y in eventCirclesSinkless: c.stroke(path.circle(x, y, 0.02), [style.linewidth.THick, color.rgb.red]) for x, y in eventCirclesSourcless: c.stroke(path.circle(x, y, 0.02), [style.linewidth.THick, color.rgb.blue]) ### Write the PDF if os.path.splitext(self.options.outpath)[1] == '': file = os.path.join(self.options.outpath, 'system.pdf') else: file = self.options.outpath c.writePDFfile(file) print("The system layout is shown in ", file)