Umple as a Template Language (Umple-TL)
Mahmoud Husseini Orabi, Ahmed Husseini Orabi and Timothy C. Lethbridge School of Electrical Engineering and Computer Science, University Of Ottawa, 800 King Edward Avenue, Ottawa, Canada
Keywords: Umple, Umple-TL, Templates, Text Emission.
Abstract: We extend Umple, a model-oriented programming language, to incorporate text emission from templates as an integral feature. Umple as a template language (Umple-TL) is the term we use to describe the template sublanguage of Umple. Using Umple-TL, developers can benefit from synergies among UML modelling, templating and programming in several target languages (Java, C++), all in one textual language – Umple. Umple itself is written in Umple; using Umple-TL, we eliminated Umple's dependency on third-party libraries for text emission. We also support any other application developed in JET to be converted to use Umple-TL and attain benefits such as smaller and faster executables, target-language independence and IDE independence. The word ‘template’ in this paper refers to patterns for the generation of output, and not to generic types, another common use of the term.
1 INTRODUCTION formats such as XML and html, generation of modelling and programming language code (in Umple is a textual modelling language with code metaprogramming and code generation), generation generation capabilities for target languages such as of messages for inter-process communication, and Java, C++, PHP, and Ruby. plus generation of other generation of user interfaces. artifacts such as diagrams (Orabi, Orabi, and A key objective of Umple is to make software Lethbridge, 2016). A goal of Umple is to keep the development simpler by adding modelling and other Umple source as ‘master’ and to insulate the constructs to base languages. Templates are just one developer from ever having to see generated code. of the many abstractions that have been added to Users write models in Umple, and inject any Umple as a necessary step to achieve Umple’s overall additional needed target-language code directly into goals. Our intent is to obtain synergies by combining the textual model. An alternative and equivalent templates with modelling in an easy-to-use language. perspective is that Umple model constructs can be A distinguishing feature of Umple-TL is that it injected into target-language code to simplify it and supports template development for multiple target reduce its bulk. languages, allowing reuse of templates across such In this paper, we show how we extended Umple languages. to act as a template language, so all text emission can We will explain how Umple as a Template be entirely represented in Umple. The word Language (Umple-TL) is used. The examples shown ‘template’ here refers to patterns of text to output, not in this paper can be instantly run in the UmpleOnline to generic types, which is another use of the term online editor (try.umple.org), the Umple Eclipse ‘template’ in programming languages. plugin or the Umple command line compiler. Languages such as PHP were designed with generation of textual output as their motivating use case. But languages such as Java do not come with 2 MAIN CONCEPTS built-in template mechanisms and rely on verbose method calls to generate text. There are three key types of textual entity involved in There are a wide variety of contexts where Umple-TL: generating formatted textual content is an essential Umple Source Text: This is the master code of the requirement: These include generation of data system under development. It includes templates,
96
Orabi, M., Orabi, A. and Lethbridge, T. Umple as a Template Language (Umple-TL). DOI: 10.5220/0007382000960104 In Proceedings of the 7th International Conference on Model-Driven Engineering and Software Development (MODELSWARD 2019), pages 96-104 ISBN: 978-989-758-358-2 Copyright c 2019 by SCITEPRESS – Science and Technology Publications, Lda. All rights reserved
Umple as a Template Language (Umple-TL)
model constructs, and target-language (e.g. Java, method, including in the expression blocks of other C++) methods. Umple-TL is simply the elements of templates. For better usability, parentheses are the Umple language that relate to generation of text optional when no parameters are defined similarly to from templates. The Umple compiler processes the languages such as Scala (Snippet 6 – Line 4). source text to produce the following: Compiled (Generated) Code: This is generated by 1 class TemplateTest1{ Umple the Umple compiler in a target language (e.g. C++. 2 t1 <> Java), and is intended to be ignored by the 3 emit e1()(t1); programmer (as would be byte code and other 4 } intermediate languages). This is executed to produce Snippet 1: A simple Umple-TL example. the following: Runtime Output Text: This is the output when the Table 1: A summary of the syntax for the blocks used to compiled code is executed. The runtime output could write templates in Umple-TL. be any type of text, including error messages, html, Block type Description and so on. If the Umple source text describes a <> Top Level: Defines the start and compiler, then the runtime output would be code end of a template body. The {b} itself. This is the case with Umple, which compiles represents arbitrary text to output, itself; in fact a key motivation for Umple-TL to make with any of the following nested it easier for Umple to be used to develop its own code within. generators (Orabi, 2017). The two key elements in Umple-TL source text <<={e} >> Expression: Computes strings to are templates themselves and emitter methods. be inserted into the text. The {e} Templates: These describe the runtime represents any expression in the output text to be generated. A template is a target language that returns a string, such as a variable or specialized Umple attribute with a unique method invocation. label and a body defined within a block delimited by <>. Table 1 describes <<# {c} #>> Code: Code in the target language the blocks that can be nested inside the outer to define logical conditions (e.g. delimiters. to make output of parts of the Emitter Methods: These are invoked to template optional) and loops. The create outputs based on one or more content of code blocks is not templates. The keyword ‘emit’ is used to appended to the runtime output indicate these (Snippet 1 – Line 3). text, but instead appears in the Since an Umple-TL template is an attribute, it compiled code. must follow the naming rules of attributes – a name <> Comment: Material not added to cannot start with a number, nor have the same name the runtime output, but which does as any other attribute or template. appear in the compiled code. It Similarly, an emitter method is a specialized must be in the syntax of the target Umple method, meaning that it must follow the language used. Comments could naming conventions imposed on normal Umple also be placed in code blocks, but methods. Arguments to the emitter method are using comment blocks can be referred to in expression and code blocks. simpler. At least one emitter method and one template are <<$ >> Exact space: Specifies required for a class to be recognized as a template whitespace that will appear at the class. Emitter methods are required since they enable beginning of every line in the passing of arguments to templates, and composing runtime output text. multiple templates.
2.1 Usage of the Various Blocks Line 2 of Snippet 2 shows the use of a code block delineated by <<# and #>>. The code in the block can Snippet 1 shows a simple template labelled as t1 (Line be in any target language that Umple supports, which 2) that is used by emitter method, e1 (Line 3). The includes Java and C++. The examples shown in this emitter method in this case has no arguments and can paper use Java. It is the developer's responsibility to be called from any part of the system as a normal
97
MODELSWARD 2019 - 7th International Conference on Model-Driven Engineering and Software Development
write valid code according to the target language of By default, whitespace appears in the runtime their selection. output as it appears in the template. However, a given template may need to generate different indentation 1 class TemplateTest2{ Umple (whitespace at the start of lines) in different contexts. 2 t2a <>This will be output if b is true !>> This can be necessary, for example, when code is 3 t2b <> being generated, and the structure of the code needs 4 emit e2(Boolean b)(t2a, t2b); to be readable. 5 } To control the indentation in runtime output, the Snippet 2: Umple-TL example illustrating a code block and developer can write an exact space block. This will multiple templates. fix the indentation of its contents no matter how that output is generated (e.g. from an expression, variable, Lines 4 of Snippet 2 also shows an emitter method or plain text). e2() that has an argument, b, referred to in template In Snippet 5, there are two templates, t2a (Line 2). The emitter method also demonstrates internalTemplate and t5. In Line 2, t5 internally emission of two templates. invokes generated emitter method internalGenerate() In Snippet 3, there are two variables string1 (Line using exact space markers. There are four 2) and string2 (Line 3). Umple creates a getter method whitespaces after the <<$. These four spaces will for any public attribute (Lines 5 and 6) in a class; appear in all lines of the runtime output. hence getString1() and getString2() will be generated, although code in a generated class can still access the 1 class TemplateTest5{ Umple variable directly without using these methods. The 2 t5 <>,!>> snippet has two expression blocks. The first uses the 3 internalTemplate<> getString1(), and the second directly appends the 4 5 value of string2. emit generate()(t5); 6 private emit internalGenerate()(internalTemplate); 7 } 1 class TemplateTest3{ Umple 2 String string1; Snippet 5: An example of exact space handling. 3 String string2; 4 Alternatively, developers can directly use the 5 t3<>; String2= generated emission method generate() and pass as a 6 <<=string2>>!>> 7 emit generate1()(t3); second argument the amount of indentation required. 8 } 2.2 Emitter Methods Snippet 3: Using assign statements in Umple-TL. An emitter method behaves like a regular method A developer can use a combination of expression (Snippet 6), but instead of writing a method body, the and code blocks. Snippet 4 shows an example of an developer simply lists templates to be used for text expression block that uses a for loop to repeatedly emission. print out parts of the content of the template block the A generated emitter method will output the number of times indicated by the argument iterations. content of all of the referenced templates. The templates will be concatenated in the order they are 1 class TemplateTest4{ Umple specified. 2 t4 <> 4 <<# for(int index=0; name of an emitter method, the first is a list of 5 index
Snippet 4 also shows a comment block in line 3.
98
Umple as a Template Language (Umple-TL)
1 class TemplateTest{ Umple associations, state machine, and composite structure. 2 t6 <> Separation of concerns features include mixins, traits 3 public static emit generate1()(t6); and aspects (Badreddin, Lethbridge, and Forward, 4 emit generate2(t6); 2014). This synergy is one of the key contributions of 5 } our work. In this section, we will focus on using Snippet 6: Emitter method examples. 1 class Course { Umple Snippet 7 shows an example of an emitter method 2 String name; 3 String description; that outputs three templates. 4 0..1 -- * Student student; 5 cr <> 2 t7a <> 7 3 t7b <> 8 courseInfo <> 4 t7d <> 10 Description: <<=getDescription()>> 5 11 Number of registered students: <<=numberOfStudent()>> 6 emit generate1()(t7a, t7b, t7c); 12 <<# switch(getStatus()) {#>><<# case Opened:#>> 7 } 13 <<# switch(getStatusOpened()) {#>><<# case 14 WithoutLateRegistrationFees:#>> Snippet 7: Multiple references to templates in an emitter 15 Last day to register without late fees <<=d1>> method. 16 <<# case WithLateRegistrationFees :#>> 17 Last day to register with late fees <<=d2>> 18 <<# } #>> Line 9 of Snippet 8, shows an emitter method 19 <<# case Registered:#>> internalGenerate() marked private. As such, it can 20 Last day to withdraw from a course <<=d2>> only be called internally to the class; in this example 21 <<# } #>> it is invoked by another template t8 (Line 3). 22 !>> 23 24 status{ 1 class TemplateTest{ Umple 25 Opened { 2 internalTemplate<> 26 register -> Registered; 3 t8<>!>> 27 close -> Closed; 4 28 WithoutLateRegistrationFees { 5 emit generate()(t8); 29 register -> Registered; 6 private emit internalGenerate()(internalTemplate); 30 deadLinePassed -> WithLateRegistrationFees; 31 } 7 } 32 WithLateRegistrationFees { Snippet 8: An internal invocation of an emitter method. 33 register -> Registered; 34 deadLinePassed -> Closed; 35 } The basic distinction between an emitter method 36 } and template, is that an emitter method is used to 37 utilize a template or a group of templates, and to 38 Registered { 39 requestToWithdrow -> Withdrawn; define other features such as formatting. In order to 40 LastDayToWithdraw { improve usability in the future, we are considering 41 requestToWithdrow -> Withdrawn; generating a default emitter method for each 42 deadLinePassed -> Closed; template, such that users can directly define templates 43 } 44 } without needing to define emitter methods if there is 45 Withdrawn { } no special logic behind using these templates. 46 Closed { 47 open -> Opened; 48 } 49 } 3 UML CONSTRUCTS AND 50 51 emit printCourseInfo(String d1, String d2, GENERATION TEMPLATES 52 String, d3 )(courseInfo, cr); 53 } We have described how to use Umple-TL to 54 55 class Student{ implement basic features needed in template 56 String name; generation. In this section, we show how Umple-TL 57 Integer id; can use the UML modelling, separation-of-concerns 58 } and template features of Umple in a synergistic way. Snippet 9: An example of using UML constructs to develop Umple UML modelling constructs include templates.
99
MODELSWARD 2019 - 7th International Conference on Model-Driven Engineering and Software Development
templates with state machines. 1 Student student1 = new Student("Name1", 1234); Java Snippet 9 shows an Umple model that displays 2 Student student2 = new Student("Name2", 432); course information based on the number of the 3 String d1=”JA 1”; String d2=”FE 1”; String d3=”AP 1”; registered students. A student has a name and id, 4 while a course has a name and description. According 5 Course course = new Course("Course1", "This is a course"); 6 course.addStudent(student1); to Line 4, there is an association defined between a 7 course.addStudent(student2); course and students. A course can have zero or more 8 students and a student may or may not be in a course. 9 System.out.println(course.printCourseInfo(d1,d2,d3)); A course has four statuses, Opened (Line 25), 10 //Course: Course1 11 //Description: This is a course Registered (Line 38), Withdrawn (Line 45), and 12 //Number of registered students: 2 Closed (Line 46). Based on the status, the displayed 13 //Last day to register without late registration fees JA 1 template information changes. If a course status is 14 //Last day to register with late registration fees FE 1 Opened, all information including fees will be 15 //Last day to withdraw from a course AP 1 16 displayed; otherwise, it is not shown. The description 17 course.close(); and number of students is displayed regardless of 18 System.out.println(course.printCourseInfo(d1,d2,d3)); course status. If a course is in the Registered status, 19 //Course: Course1 information such as last day to withdraw is shown. 20 //Description: This is a course 21 //Number of registered students: 2 Figure 1 shows the state machine defined in 22 Snippet 9 (generated automatically by Umple). The 23 course.open(); logic of the state machine is given textually in Lines 24 System.out.println(course.printCourseInfo(d1,d2,d3)); 24-49. 25 //Course: Course1 26 //Description: This is a course 27 //Number of registered students: 2 28 //Last day to register without late registration fees JA 1 29 //Last day to register with late registration fees FE 1 30 //Last day to withdraw from a course AP 1 31 32 course.register(); 33 System.out.println(course.printCourseInfo(d1,d2,d3)); 34 //Course: Course1 35 //Description: This is a course 36 //Number of registered students: 2 37 //Last day to withdraw from a course AP 1 Snippet 10: An invocation example of Snippet 9.
Finally, In Line 31, we change the status to Registered. This is similar to Closed state, but Figure 1: The state machine diagram of Snippet 9. additionally shows the last day to withdraw (Lines 34-37). Snippet 10 shows an execution of the generated code of Snippet 9. For simplicity, we show the 3.1 Declarative Examples console output in green as lines of comments. In Snippet 10, we define two students and add both to a In this section, we show two Umple-TL examples for course. A course status is "Opened" by default. The HTML page generation. The first example (Snippet first information printed is full course information, 11) is more tailored, and hence requires a few lines to given that the course status is Opened. The output is execute (Snippet 12). The second example (Snippet shown in Lines 10-15. 13) is more abstract, so it can support dynamic table In Line 17, we change the status of the course to generation, but will require more lines of code to be Closed. The output in that case, Lines 19-21, only define custom tables (Snippet 14). shows the basic information about the course and its In Snippet 13, HtmlNode has two attributes, tag students. and content. The tag attribute refers to a valid html We change the status back to Opened (Snippet 10- tag such as html or body. The "content" attribute is Line 23). Now the lines to be printed are as in Lines optional and has an empty value by default; it refers 25-30, which are identical to the Lines 10-14. to the text content of an html node. There is an association attribute; "children". Associations are one
100
Umple as a Template Language (Umple-TL)
1 class HtmlTemplate { Umple nested ways. The "nested" template is used to take 2 htmlTemplate < 4
instance; a child node itself can have a list of children. 51 HtmlNode html = new HtmlNode("html"); Java 9 <<=name>> 2 HtmlNode body = new HtmlNode("body"); 10 | 3 html.addChild(body); 11