PSL and PLSL - MDSE Research Group

46
T ECHNICAL R EPORT Report No. UI-SE-MDSERG-2016-06 Date: January 31, 2017 The Xtext generated parsers to specify patterns and pattern languages: PSL and PLSL Alireza Rouhi Bahman Zamani Department of Software Engineering University of Isfahan Hezar-Jerib Ave. Isfahan Tel: +98-31-37934537 Fax: +98-31-36699529 , +98-31-37932670 [email protected] http://mdse.bahmanzamani.com/

Transcript of PSL and PLSL - MDSE Research Group

TECHNICAL REPORT

Report No. UI-SE-MDSERG-2016-06Date: January 31, 2017

The Xtext generated parsers tospecify patterns and patternlanguages: PSL and PLSL

Alireza RouhiBahman Zamani

Department of Software EngineeringUniversity of IsfahanHezar-Jerib Ave.Isfahan

Tel: +98-31-37934537Fax: +98-31-36699529 , [email protected]

http://mdse.bahmanzamani.com/

The Xtext generated parsers to specifypatterns and pattern languages: PSL and

PLSL

Alireza Rouhi and Bahman ZamaniDepartment of Software Engineering

University of IsfahanIsfahan, Iran.

{rouhi, zamani}@eng.ui.ac.ir

Abstract: In this report, we aim at presenting the Xtext gener-ated parsers named the Pattern Specification Language (PSL) andthe Pattern Language Specification Language (PLSL) parsers to fa-cilitate the tedious and error-prone process of writing and validatingthe specification of design patterns and PLs in our presented patternspecification scheme and PL formalism in UI-SE-MDSERG-2015-01. Utilizing the generated tools, we revised our earlier presentedspecification of the patterns of the Broker PL in UI-SE-MDSERG-2015-01 as a case study. The good news is that several typing andlogical errors have been found and corrected by using the producedPSL parser. In this report, we present the Broker PL specificationas a case-study to show the applicability of the generated PSL andPLSL parsers. Finally, the Xtext source code representing the PSLand PLSL parsers are presented.

The Xtext generated parsers to specifypatterns and pattern languages: PSL and

PLSL

Alireza Rouhi and Bahman ZamaniDepartment of Software Engineering

University of IsfahanIsfahan, Iran.

{rouhi, zamani}@eng.ui.ac.ir

Abstract: In this report, we aim at presenting the Xtext gener-ated parsers named the Pattern Specification Language (PSL) andthe Pattern Language Specification Language (PLSL) parsers to fa-cilitate the tedious and error-prone process of writing and validatingthe specification of design patterns and PLs in our presented patternspecification scheme and PL formalism in UI-SE-MDSERG-2015-01. Utilizing the generated tools, we revised our earlier presentedspecification of the patterns of the Broker PL in UI-SE-MDSERG-2015-01 as a case study. The good news is that several typing andlogical errors have been found and corrected by using the producedPSL parser. In this report, we present the Broker PL specificationas a case-study to show the applicability of the generated PSL andPLSL parsers. Finally, the Xtext source code representing the PSLand PLSL parsers are presented.

Contents

1 Introduction 2

1.1 Xtext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2 Eclipse Modeling Framework (EMF) Metamodeling . . . . . . . . . . 3

2 The PSL parser in action 4

2.1 The Broker Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.2 The Wrapper Facade Pattern . . . . . . . . . . . . . . . . . . . . . . 8

2.3 The Reactor Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1

2.4 The Acceptor and Connector Pattern . . . . . . . . . . . . . . . . . . 12

2.5 The Leader/Followers Pattern . . . . . . . . . . . . . . . . . . . . . . 17

2.6 The Half-Sync/Half-Async Pattern . . . . . . . . . . . . . . . . . . . 22

2.7 The Monitor Object Pattern . . . . . . . . . . . . . . . . . . . . . . . 24

2.8 The Abstract Factory Pattern . . . . . . . . . . . . . . . . . . . . . . 28

2.9 The Component Configurator Pattern . . . . . . . . . . . . . . . . . . 30

3 The PLSL parser in action 33

A The PSL source code in Xtext 33

B The PLSL source code in Xtext 38

1 Introduction

To write and validate a given Pattern Language (PL) and its patterns with ourpresented formalism of a PL in [RZ16], we developed two languages named PLSLand PSL, respectively, to specify a given PL and its patterns. These languages havebeen generated automatically using the Xtext parser generator tool.

In this report, first we present a brief introduction to Xtext [Bet13] and EMF [SBMP08,Gro09]. This materials helps a designer to understand the specification of patternsand PLs in PSL and PLSL. As a case study, we present the PSL listings of the pat-terns of the Broker PL. Finally, we present the Xtext source code representing thePSL and PLSL parsers in Section A and Section B, respectively.

1.1 Xtext

Xtext is an Eclipse-based open-source framework to develop Domain-Specific Lan-guages (DSLs) [Bet13] by a programmer in a quick manner. One of the most im-portant and valuable advantages of using Xtext is its tool support on automaticgeneration of Eclipse-based Integrated Development Environment (IDE) plug-ins todeploy the produced DSL artifacts [EB10].

Since, Xtext supports a grammar notation similar to Extended BNF (EBNF) asits input which nearly matches with the revised and extended Graphic extension

2

of EBNF (GEBNF) notation, translating the proposed formal model of the patternspecification scheme [RZ16] to the Xtext’s input format is performed easily.

Listing 10 in Section A demonstrates the PSL’s parser generation code in Xtext.Additionally, Listing 11 in Section B demonstrates the PSL’s parser generation code inXtext. See [RZ15] for more information about the syntax definition and programmingas well as running a sample example in Xtext.

In the following, we present a brief introduction to the EMF metamodeling.

1.2 EMF Metamodeling

A model is defined as an abstraction of a real system. A metamodel itself is alanguage or a model with a higher abstraction level than a model which conformsto the metamodel [JB06, BCW12]. A model conformance to a metamodel is muchlike as a program script respecting its grammar specification. These two developmentparadigms are known as Modelware and Grammarware, respectively [PKP14].

Xtext is compatible with the Eclipse EMF. EMF can be used to define a domainmodel in general. Here, to have a background in the EMF tool suite, we present abrief introduction [SBMP08, Gro09].

The EMF metamodel itself has two base metamodels: the Ecore model and theGenmodel model. The Ecore model contains information regarding each model’sdefined classifiers. In contrast, the Genmodel provides the required additional andcontrol information for the code generation and direction; for example, the path ofthe stored model and related files information.

Each Ecore model defines the following elements:

• EClass: a class representation which can contain zero or more attributes aswell as zero or more references.

• EAttribute: a named attribute representation which can have a type too.

• EReference: an association end representation between two classes. A refer-ence can be a containment of or be contained in other class which is indicatedby setting a flag.

• EDatatype: an attribute type representation, for example, int and boolean forprimitive types and java.util.Date for an object type.

3

+send_request()+return()

C_Proxy

+call_server()

Client

+find_server()+forward_request()+find_client()+forward_response()

Broker

+forward_message()+transmit_message()

Bridge

+run_service()

Server

+call_service()+send_response()

S_Proxy

+call_server()

<<Interface>>C_API

+register_service()

<<Interface>>S_API

usesuses

calls

1..*

1..*

calls

1..*

1..*

1..*

1..*

1..* 1

0..*

1..*1..*

1..*

10..*

0..*1

1..*1 providesprovides

transferstransfers

Figure 1: The Broker pattern class diagram (changed from [BMR+96])

2 The PSL parser in action

In this section, the revised and validated version of patterns of the Broker PL [BHS07]are presented.

2.1 The Broker Pattern

Figure 1 and Figure 2 show the class diagram of the Broker pattern (changed from[BMR+96]) and a simple scenario of its sequence diagram, respectively.

Figure 3 displays the PSL Editor usage in practice. Listing 1 demonstrates the Brokerpattern PSL code.

1 patternName:

2 Broker

3

4 components:

5 {Broker, Client, C_Proxy, C_API, Bridge, S_API, S_Proxy, Server} SUBSETEQ classes();

6 call_server() IN opers(Client);

7 {send_request(), cpreturn()} SUBSETEQ opers(C_Proxy);

8 call_server() IN opers(C_API);

9 {find_server(), forward_request(), find_client(), forward_response()} SUBSETEQ opers(Broker);

10 {forward_message(), transmit_message()} SUBSETEQ opers(Bridge);

11 register_service() IN opers(S_API);

12 {call_service(), send_response()} SUBSETEQ opers(S_Proxy);

13 run_service() IN opers(Server);

14

4

ServerS_ProxyBrokerC_ProxyCleint

forward_response()

call_service()

send_response()

run_service()

return()

find_client()

forward_request()

call_server()

send_request()

Figure 2: The Broker pattern sequence diagram (changed from [BMR+96])

5

Figure 3: The PSL Editor

15 staticConditions:

16 associates(Client, C_Proxy) ^

17 associates(C_Proxy, Client) ^

18 associates(Server, S_Proxy) ^

19 associates(S_Proxy, Server) ^

20 associates(Broker, Broker) ^

21 associates(Broker, Bridge)^

22 associates(Bridge, Broker) ^

23 associates(Bridge, Bridge) ^

24 associates(C_Proxy, Broker) ^

25 associates(Broker, C_Proxy) ^

26 associates(S_Proxy, Broker) ^

27 associates(Broker, S_Proxy) ^

28 depends(Client, C_API) ^

29 depends(Server, S_API) ^

30 composes(Broker, C_API) ^

31 composes(Broker, S_API) ^

32 isInterface(C_API) ^

33 isInterface(S_API) ^

34

35 dynamicConditions:

36 FORALL M: Message @

37 (M IN msgs() ^

38 sig(M) = call_server() ^

39 name(c(name(lifeline(sender(M))))) = Client ^

6

40 name(c(name(lifeline(receiver(M))))) = Client

41 )

42 =>

43 (EXISTS M_c: Message |

44 (M_c IN msgs() ^

45 sig(M_c) = send_request() ^

46 name(c(name(lifeline(sender(M_c))))) = Client ^

47 name(c(name(lifeline(receiver(M_c))))) = C_Proxy)

48 => (precedes(M_5, M_c) ^ calls(call_server(), send_request())) ^

49 EXISTS M_b: Message | (M_b IN msgs() ^

50 sig(M_b) = forward_request() ^

51 name(c(name(lifeline(sender(M_b))))) = C_Proxy ^

52 name(c(name(lifeline(receiver(M_b))))) = Broker) =>

53 (precedes(M_c, M_b) ^

54 calls(send_request(), forward_request())) ^

55 EXISTS M_sp: Message | (M_sp IN msgs() ^

56 sig(M_sp) = call_service() ^

57 name(c(name(lifeline(sender(M_sp))))) = Broker ^

58 name(c(name(lifeline(receiver(M_sp))))) = S_Proxy) =>

59 (precedes(M_b, M_sp) ^

60 calls(forward_request(), call_service())) ^

61 EXISTS M_s: Message | (M_s IN msgs() ^

62 sig(M_s) = run_service() ^

63 name(c(name(lifeline(sender(M_s))))) = S_Proxy ^

64 name(c(name(lifeline(receiver(M_s))))) = Server) =>

65 (precedes(M_sp, M_s) ^

66 calls(call_service(), run_service())) ^

67 EXISTS M_rsp: Message | (M_rsp IN msgs() ^

68 sig(M_rsp) = send_response() ^

69 name(c(name(lifeline(sender(M_rsp))))) = Server ^

70 name(c(name(lifeline(receiver(M_rsp))))) = S_Proxy) =>

71 (precedes(M_s, M_rsp) ^

72 calls(run_service(),send_response())) ^

73 EXISTS M_rb: Message | (M_rb IN msgs() ^

74 sig(M_rb) = forward_response() ^

75 name(c(name(lifeline(sender(M_rb))))) = S_Proxy ^

76 name(c(name(lifeline(receiver(M_rb))))) = Broker) =>

77 (precedes(M_rsp, M_rb) ^

78 calls(send_response(),forward_response())) ^

79 EXISTS M_rbb: Message | (M_rbb IN msgs() ^

80 sig(M_rbb) = find_client() ^

81 name(c(name(lifeline(sender(M_rbb))))) = Broker ^

82 name(c(name(lifeline(receiver(M_rbb))))) = Broker) =>

83 precedes(M_rb, M_rbb) ^

84 EXISTS M_rcp: Message | (M_rcp IN msgs() ^

85 sig(M_rcp) = cpreturn() ^

86 name(c(name(lifeline(sender(M_rcp))))) = Broker ^

87 name(c(name(lifeline(receiver(M_rcp))))) = C_Proxy) =>

7

+do_something()

Client +service_1()+service_2()+service_3()

Wrapper Facade

+func_1()+func_2()+func_3()+func_4()

Functions

calls

calls

Figure 4: The Wrapper Facade pattern class diagram (revised from [Sch99, BHS07])

88 (precedes(M_rbb, M_rcp) ^

89 calls(find_client(), cpreturn()))

90 )

Listing 1: The Broker pattern specification in PSL

2.2 The Wrapper Facade Pattern

Figure 4 and Figure 5 show the class diagram and sequence diagram representing thispattern, respectively.

Listing 2 demonstrates the Wrapper Facade pattern PSL code.

1 patternName:

2 WrapperFacade

3

4 components:

5

6 {WrapperFacade, Client, Functions} SUBSETEQ classes();

7 do_something() IN opers(Client);

8 service() IN opers(WrapperFacade);

9 func() IN opers(Functions);

10

11 staticConditions:

12

13 depends(Client, WrapperFacade) ^

14 depends(WrapperFacade, Functions)

15

16 // Each WrapperFacade must reference at least one Functions class

17 FORALL WR: WrapperFacade =>

18 EXISTS F: Functions => depends(WR, F)

19

8

FunctionsWrapperFacade

Client

func_1()

func_2()

do_something()

service_2()

Figure 5: The Wrapper Facade pattern sequence diagram (revised from [Sch99,BHS07])

20 dynamicConditions:

Listing 2: The Wrapper Facade pattern specification in PSL

2.3 The Reactor Pattern

Figure 6 and Figure 7 show the class diagram and sequence diagram representing thispattern, respectively.

Listing 3 demonstrates the Reactor pattern PSL code.

+registerHandler()+removeHandler()+dispatch()+waitForEvents()

Reactor AbstractEventHandler+handleEvent()+getHandle()+handleClose()

+handleEvent()+handleClose()+getHandle()

ConcreteEventHandler

handlers

0..*

1

getHandle()

Figure 6: The Reactor pattern class diagram (revised from [Sch95, BHS07])

9

Client ReactorCocreteEventHandler

create()

handleClose()

handleEvent()waitForEvents()

dispatch()

getHandle()

registerHandler()

Figure 7: The Reactor pattern sequence diagram (revised from [Sch95, BHS07])

1 patternName:

2 Reactor

3

4 components:

5

6 {Reactor, AbstractEventHandler, ConcreteEventHandler} SUBSETEQ7 classes();

8 {registerHandler(), removeHandler(), dispatch(), waitForEvents()} SUBSETEQ9 opers(Reactor);

10 {handleEvent(), getHandle(), handleClose()} SUBSETEQ11 opers(AbstractEventHandler);

12 {handleEvent(), getHandle(), handleClose()} SUBSETEQ13 opers(ConcreteEventHandler);

14

15 staticConditions:

16

17 isAbstract(AbstractEventHandler) ^

18 depends(Reactor, ConcreteEventHandler) ^

19 aggregates(Reactor, AbstractEventHandler) ^

20 inherits(ConcreteEventHandler, AbstractEventHandler) ^

21

22 // Each abstract AbstractEventHandler must be inherited by

23 // at least one non-abstract ConcreteEventHandler

24 FORALL AEH: AbstractEventHandler @ isAbstract(AEH) =>

25 EXISTS CEH: ConcreteEventHandler => (~isAbstract(CEH) ^ inherits(CEH, AEH))

26

27 dynamicConditions:

28

29 FORALL M: Message @

30 (M IN msgs() ^

10

31 name(c(name(lifeline(sender(M))))) = Client ^

32 name(c(name(lifeline(receiver(M))))) = Reactor ^

33 sig(M) = registerHandler())

34 =>

35 EXISTS MC_2: Message |

36 (MC_2 IN msgs() ^

37 sig(MC_2) = getHandle() ^

38 name(c(name(lifeline(sender(MC_2))))) = Reactor ^

39 name(c(name(lifeline(receiver(MC_2))))) = ConcreteEventHandler) =>

40 precedes(M, MC_2) ^

41 FORALL M: Message @

42 (M IN msgs() ^

43 name(c(name(lifeline(sender(M))))) = Client ^

44 name(c(name(lifeline(receiver(M))))) = Reactor ^

45 sig(M) = dispatch())

46 =>

47 EXISTS MR_2: Message |

48 (MR_2 IN msgs() ^

49 sig(MR_2) = waitForEvents() ^

50 name(c(name(lifeline(sender(MR_2))))) = Reactor ^

51 name(c(name(lifeline(receiver(MC_2))))) = Reactor) =>

52 precedes(M, MR_2) ^

53 FORALL M: Message @

54 (M IN msgs() ^

55 name(c(name(lifeline(sender(M))))) = Reactor ^

56 name(c(name(lifeline(receiver(M))))) = ConcreteEventHandler ^

57 sig(M) = handleEvent())

58 =>

59 EXISTS MC_2: Message |

60 (MC_2 IN msgs() ^

61 sig(MC_2) = handleClose() ^

62 name(c(name(lifeline(sender(MC_2))))) = Reactor ^

63 name(c(name(lifeline(receiver(MC_2))))) = ConcreteEventHandler) =>

64 precedes(M, MC_2) ^

65 FORALL M_1, M_2: Message |

66 (M_1 IN msgs() ^

67 M_2 IN msgs()) @

68 (sig(M_1) = handleClose() ^

69 sig(M_2) = removeHandler())

70 =>

71 precedes(handleClose(), removeHandler())

Listing 3: The Reactor pattern specification in PSL

11

+connect()+handleEvents()+complete()

Connector

+accept()+makeSrvHandler()+acceptSrvHandler()+operation()+handleEvent()+handleClose()

Acceptor

+open()+getHandle()+handleEvent()+service()

CServiceHandler

+connect()

Client

+open()

Server

+select()+registerHandler()+handleEvents()

Reactor

+open()+activateSrvHandler()+getHandle()+handleEvent()+service()+handleClose()

SServiceHandler

Figure 8: The Acceptor and Connector pattern class diagram (revised from [Sch96,BHS07])

2.4 The Acceptor and Connector Pattern

Figure 8, Figure 9, and Figure 10 show the class diagram and sequence diagramsrepresenting this pattern, respectively.

Listing 4 demonstrates the Acceptor and Connector pattern PSL code.

1 patternName:

2 AcceptorConnector

3

4 components:

5

6 {Connector, Client, CServiceHandler, Reactor, Server,

7 Acceptor, SServiceHandler} SUBSETEQ classes();

8 connect() IN opers(Client);

9 {connect(), handleEvents(), complete()} SUBSETEQ opers(Connector);

10 {open(), getHandle(), handleEvent(), service()} SUBSETEQ opers(CServiceHandler);

11 {select(), registerHandler(), handleEvents()} SUBSETEQ opers(Reactor);

12 {accept(), makeSrvHandler(), acceptSrvHandler(), operation(),

13 handleEvent(), handleClose()} SUBSETEQ opers(Acceptor);

14 {open(), activateSrvHandler(), getHandle(), handleEvent(),

15 service(), handleClose()} SUBSETEQ opers(SServiceHandler);

16 open() IN opers(Server);

17

18 staticConditions:

12

ReactorSServiceHandler

AcceptorServer

handleClose()

service()

handleClose()

handleEvent()

getHandle()

handleEvent()

getHandle()

registerHandler()

select()

handleEvents()

registerHandler()

activateSrvHandler()

acceptSrvHandler()

makeSrvHandler()

open()

Figure 9: The Acceptor pattern sequence diagram (adapted from [Sch96, BHS07])

13

ReactorCServiceHandler

ConnectorClient

service()

handleEvent()

getHandle()

registerHandler()

complete()

open()

handleEvent()select()

handleEvents()

registerHandler()

connect()

Figure 10: The Connector pattern sequence diagram with the asynchronous initial-ization (adapted from [Sch96, BHS07])

14

19

20 depends(Client, Reactor) ^

21 depends(Client, Connector) ^

22 depends(Connector, Reactor) ^

23 depends(Connector, Acceptor) ^

24 depends(Server, Reactor) ^

25 depends(Server, Acceptor) ^

26 associates(CServiceHandler, Reactor) ^

27 associates(CServiceHandler, SServiceHandler) ^

28 associates(Acceptor, Reactor) ^

29 associates(SServiceHandler, Reactor) ^

30 associates(Acceptor, SServiceHandler)

31

32 dynamicConditions:

33

34 // Acceptor

35 (FORALL M: Message @

36 (M IN msgs() ^

37 name(c(name(lifeline(sender(M))))) = Server ^

38 name(c(name(lifeline(receiver(M))))) = Acceptor ^

39 sig(M) = open())

40 =>

41 ((EXISTS MR_2, MA_3: Message |

42 ({MR_2, MA_3} SUBSETEQ msgs() ^

43 sig(MR_2) = registerHandler() ^

44 sig(MA_3) = getHandle() ^

45 name(c(name(lifeline(sender(MR_2))))) = Acceptor ^

46 name(c(name(lifeline(receiver(MR_2))))) = Reactor ^

47 name(c(name(lifeline(sender(MA_3))))) = Reactor ^

48 name(c(name(lifeline(receiver(MA_3))))) = Acceptor) =>

49 (precedes(M, MR_2) ^ precedes(MR_2, MA_3))) ^

50 (EXISTS MR_4, MR_5: Message |

51 ({MR_4, MA_5} SUBSETEQ msgs() ^

52 sig(MR_4) = handleEvents() ^

53 sig(MA_3) = select() ^

54 name(c(name(lifeline(sender(MR_4))))) = Server ^

55 name(c(name(lifeline(receiver(MR_4))))) = Reactor ^

56 name(c(name(lifeline(sender(MR_5))))) = Reactor ^

57 name(c(name(lifeline(receiver(MR_5))))) = Reactor) =>

58 (precedes(M, MR_4) ^ precedes(MR_4, MR_5))) ^

59 (EXISTS MA_6, MA_7, MA_8, MA_9: Message |

60 ({MA_6, MA_7, MA_8, MA_9} SUBSETEQ msgs() ^

61 sig(MA_6) = handleEvent() ^

62 sig(MA_7) = makeSrvHandler() ^

63 sig(MA_8) = acceptSrvHandler() ^

64 sig(MA_9) = activateSrvHandler() ^

65 name(c(name(lifeline(sender(MA_6))))) = Reactor ^

66 name(c(name(lifeline(receiver(MA_6))))) = Acceptor ^

15

67 name(c(name(lifeline(sender(MA_7))))) = Acceptor ^

68 name(c(name(lifeline(receiver(MA_7))))) = Acceptor ^

69 name(c(name(lifeline(sender(MA_8))))) = Acceptor ^

70 name(c(name(lifeline(receiver(MA_8))))) = Acceptor ^

71 name(c(name(lifeline(sender(MA_9))))) = Acceptor ^

72 name(c(name(lifeline(receiver(MA_9))))) = SServiceHandler) =>

73 (precedes(MR_5,MA_6) ^ precedes(MA_6,MA_7) ^

74 precedes(MA_7,MA_8) ^ precedes(MA_8,MA_9))) ^

75 (EXISTS MR_10, MSS_11, MSS_12, MSS_13, MSS_14, MA_15: Message |

76 ({MR_10, MSS_11, MSS_12, MSS_13, MSS_14, MA_15} SUBSETEQ msgs() ^

77 sig(MR_10) = registerHandler() ^

78 sig(MSS_11) = getHandle() ^

79 sig(MSS_12) = handleEvent() ^

80 sig(MSS_13) = service() ^

81 sig(MSS_14) = handleClose() ^

82 sig(MA_15) = handleClose() ^

83 name(c(name(lifeline(sender(MR_10))))) = SServiceHandler ^

84 name(c(name(lifeline(receiver(MR_10))))) = Reactor ^

85 name(c(name(lifeline(sender(MSS_11))))) = Reactor ^

86 name(c(name(lifeline(receiver(MSS_11))))) = SServiceHandler ^

87 name(c(name(lifeline(sender(MSS_12))))) = Reactor ^

88 name(c(name(lifeline(receiver(MSS_12))))) = SServiceHandler ^

89 name(c(name(lifeline(sender(MSS_13))))) = SServiceHandler ^

90 name(c(name(lifeline(receiver(MSS_13))))) = SServiceHandler ^

91 name(c(name(lifeline(sender(MSS_14))))) = Reactor ^

92 name(c(name(lifeline(receiver(MSS_14))))) = SServiceHandler ^

93 name(c(name(lifeline(sender(MA_15))))) = Reactor ^

94 name(c(name(lifeline(receiver(MA_15))))) = Acceptor) =>

95 (precedes(MA_9,MR_10) ^ precedes(MR_10,MSS_11) ^

96 precedes(MSS_11,MSS_12) ^ precedes(MSS_12,MSS_13) ^

97 precedes(MSS_13,MSS_14) ^ precedes(MSS_14,MA_15)))

98 )) ^

99 // Connector

100 (FORALL M: Message @

101 (M IN msgs() ^

102 name(c(name(lifeline(sender(M))))) = Client ^

103 name(c(name(lifeline(receiver(M))))) = Connector ^

104 sig(M) = connect())

105 =>

106 ((EXISTS MR_2: Message |

107 (MR_2 IN msgs() ^

108 sig(MR_2) = registerHandler() ^

109 name(c(name(lifeline(sender(MR_2))))) = Connector ^

110 name(c(name(lifeline(receiver(MR_2))))) = Reactor) =>

111 precedes(M, MR_2)) ^

112 (EXISTS MR_3, MR_4, MC_5: Message |

113 ({MR_3, MR_4, MC_5} SUBSETEQ msgs() ^

114 sig(MR_3) = handleEvents() ^

16

115 sig(MR_4) = select() ^

116 sig(MC_5) = handleEvent() ^

117 name(c(name(lifeline(sender(MR_3))))) = Client ^

118 name(c(name(lifeline(receiver(MR_3))))) = Reactor ^

119 name(c(name(lifeline(sender(MR_4))))) = Reactor ^

120 name(c(name(lifeline(receiver(MR_4))))) = Reactor ^

121 name(c(name(lifeline(sender(MC_5))))) = Reactor ^

122 name(c(name(lifeline(receiver(MC_5))))) = Connector) =>

123 (precedes(MR_2, MR_3) ^

124 precedes(MR_3, MR_4) ^

125 precedes(MR_4, MC_5))) ^

126 (EXISTS MC_6, MCS_7: Message |

127 ({MC_6, MCS_7} SUBSETEQ msgs() ^

128 sig(MC_6) = complete() ^ sig(MCS_7) = open() ^

129 name(c(name(lifeline(sender(MC_6))))) = Connector ^

130 name(c(name(lifeline(receiver(MC_6))))) = Connector ^

131 name(c(name(lifeline(sender(MCS_7))))) = Connector ^

132 name(c(name(lifeline(receiver(MCS_7))))) = CServiceHandler) =>

133 (precedes(MC_5, MC_6) ^ precedes(MC_6, MCS_7))) ^

134 (EXISTS MR_8, MCS_9, MCS_10, MCS_11: Message |

135 ({MR_8, MCS_9, MCS_10, MCS_11} SUBSETEQ msgs() ^

136 sig(MR_8) = registerHandler() ^ sig(MCS_9) = getHandle() ^

137 sig(MR_8) = handleEvent() ^ sig(MCS_9) = service() ^

138 name(c(name(lifeline(sender(MR_8))))) = CServiceHandler ^

139 name(c(name(lifeline(receiver(MR_8))))) = Reactor ^

140 name(c(name(lifeline(sender(MCS_9))))) = Reactor ^

141 name(c(name(lifeline(receiver(MCS_9))))) = CServiceHandler ^

142 name(c(name(lifeline(sender(MCS_10))))) = Reactor ^

143 name(c(name(lifeline(receiver(MCS_10))))) = CServiceHandler ^

144 name(c(name(lifeline(sender(MCS_11))))) = CServiceHandler ^

145 name(c(name(lifeline(receiver(MCS_11))))) = CServiceHandler) =>

146 (precedes(MCS_7, MR_8) ^ precedes(MR_8, MCS_9) ^

147 precedes(MCS_9, MCS_10) ^ precedes(MCS_10, MCS_11)))))

Listing 4: The Acceptor and Connector pattern specification in PSL

2.5 The Leader/Followers Pattern

Figure 11 and Figure 12 show the class diagram and sequence diagrams representingthis pattern, respectively.

Listing 5 demonstrates the Leader/Followers pattern PSL code.

1 patternName:

2 LeaderFollowers

3

4 components:

17

+join()+promoteNewLeader()

ThreadPool

+handleEvents()+select()+eventArrival()

HandleSet

Handle

EventHandler+handleEvent()

+getHandle()

+handleEvent()+getHandle()

ConcreteEventHandler

+joinPool()+notify()

Thread

*

*

1..*

1

{ordered}

Figure 11: The Leader/Followers pattern class diagram (revised from [SOK+00,BHS07])

5

6 {ThreadPool, HandleSet, Handle, EventHandler, ConcreteEventHandler,

7 LFThread} SUBSETEQ classes();

8 {handleEvents(), select(), eventArrival()} SUBSETEQ opers(HandleSet);

9 {handleEvent(), getHandle()} SUBSETEQ opers(EventHandler);

10 {handleEvent(), getHandle()} SUBSETEQ opers(ConcreteEventHandler);

11 promoteNewLeader() IN opers(ThreadPool);

12 {join(), notify()} SUBSETEQ opers(LFThread);

13

14 staticConditions:

15

16 isAbstract(EventHandler) ^

17 associates(HandleSet, LFThread) ^

18 associates(HandleSet, Handle) ^

19 associates(ThreadPool, Handle) ^

20 associates(EventHandler, Handle) ^

21 associates(LFThread, EventHandler) ^

22 aggregates(ThreadPool, LFThread) ^

23 inherits(ConcreteEventHandler, EventHandler) ^

24

25 // Each abstract EventHandler must be inherited by

26 // at least one non-abstract ConcreteEventHandler

27 FORALL EH: EventHandler @ isAbstract(EH) =>

28 EXISTS CEH: ConcreteEventHandler =>

29 (~isAbstract(CEH) ^ inherits(CEH, EH))

30

31 dynamicConditions:

18

ConcreteEventHandler

HandleSetThreadPool T2 : ThreadT1 : Thread

joinPool()

joinPool()

joinPool()

promoteNewLeader()

notify(newFollower)

join() select()

handleEvents()

join()

notify(eventArrival)

eventArrival() select()

handleEvent()

notify(newLeader)

notify(newFollower)

handleEvents()notify(newLeader)

join()

Figure 12: The Leader/Followers pattern sequence diagram (revised from [SOK+00,BHS07])

19

32

33 (FORALL M: Message; T: Class |

34 (M IN msgs() ^

35 T IN classes() ^

36 name(T) = LFThread) @

37 (c(name(lifeline(sender(M)))) = T ^

38 c(name(lifeline(receiver(M)))) = T ^

39 sig(M) = joinPool())

40 =>

41 (EXISTS MTP_2: Message |

42 (MTP_2 IN msgs() ^

43 sig(MTP_2) = join() ^

44 c(name(lifeline(sender(MTP_2)))) = T ^

45 c(name(lifeline(receiver(MTP_2)))) = ThreadPool) =>

46 (precedes(M, MTP_2) ^ calls(joinPool(), join())))) ^

47 (FORALL M_j1, M_j2, M_n1, M_n2: Message; T_1, T_2, TP: Class |

48 ({M_j1, M_j2, M_n1, M_n2} SUBSETEQ msgs() ^

49 name(T_1) = LFThread ^

50 name(T_2) = LFThread ^

51 name(TP) = ThreadPool ^

52 {T_1, T_2, TP} SUBSETEQ classes() ^

53 c(name(lifeline(sender(M_j1)))) = T_1 ^

54 c(name(lifeline(receiver(M_j1)))) = TP ^

55 c(name(lifeline(sender(M_j2)))) = T_2 ^

56 c(name(lifeline(receiver(M_j2)))) = TP ^

57 c(name(lifeline(sender(M_n1)))) = TP ^

58 c(name(lifeline(receiver(M_n1)))) = T_1 ^

59 c(name(lifeline(sender(M_n2)))) = TP ^

60 c(name(lifeline(receiver(M_n2)))) = T_2 ^

61 sig(M_j1) = join() ^ sig(M_j2) = join()) @

62 (sig(M_n1) = notify(NewLeader) ^

63 sig(M_n2) = notify(NewFollower))

64 <=>

65 precedes(M_j1, M_j2)) ^

66 (FORALL M: Message; T_1, TP, HS: Class |

67 (M IN msgs() ^

68 {T_1, TP, HS} SUBSETEQ classes() ^

69 name(T_1) = LFThread ^

70 name(TP_1) = ThreadPool ^

71 name(HS_1) = HandleSet) @

72 (c(name(lifeline(sender(M)))) = TP ^

73 c(name(lifeline(receiver(M)))) = T_1 ^

74 sig(M) = notify(NewLeader))

75 =>

76 ((EXISTS MHS_2: Message |

77 (MHS_2 IN msgs() ^

78 sig(MHS_2) = handleEvents() ^

79 c(name(lifeline(sender(MHS_2)))) = T_1 ^

20

80 c(name(lifeline(receiver(MHS_2)))) = HS) =>

81 precedes(M, MTHS_2)) ^

82 (EXISTS MHS_3, MHS_4: Message |

83 ({MHS_3, MHS_4} SUBSETEQ msgs() ^

84 sig(MHS_3) = select() ^

85 sig(MHS_4) = eventArrival() ^

86 c(name(lifeline(sender(MHS_3)))) = HS ^

87 c(name(lifeline(receiver(MHS_3)))) = HS ^

88 c(name(lifeline(receiver(MHS_4)))) = HS) =>

89 (precedes(MHS_2, MHS_3) ^

90 precedes(MHS_3, MHS_4))) ^

91 (EXISTS MT_5, MTP_6: Message |

92 ({MT_5, MTP_6} SUBSETEQ msgs() ^

93 sig(MT_5) = notify(EventArrival) ^

94 sig(MTP_6) = promoteNewLeader() ^

95 c(name(lifeline(sender(MT_5)))) = HS ^

96 c(name(lifeline(receiver(MT_5)))) = T_1 ^

97 c(name(lifeline(sender(MTP_6)))) = T_1 ^

98 c(name(lifeline(receiver(MTP_6)))) = TP) =>

99 (precedes(MHS_4, MT_5) ^

100 precedes(MT_5, MT_6))) ^

101 (EXISTS MT_7: Message; T_2: Class |

102 (MT_7 IN msgs() ^

103 T_2 IN classes() ^

104 name(T_2) = LFThread ^

105 sig(MT_7) = notify(NewLeader) ^

106 c(name(lifeline(sender(MT_7)))) = TP ^

107 c(name(lifeline(receiver(MT_7)))) = T_2) =>

108 precedes(MT_6, MT_7)) ^

109 (EXISTS MCEH_8: Message |

110 (MCEH_8 IN msgs() ^

111 sig(MCEH_8) = handleEvent() ^

112 c(name(lifeline(sender(MCEH_8)))) = T_1 ^

113 name(c(name(lifeline(receiver(MCEH_8))))) =

114 ConcreteEventHandler) =>

115 precedes(MTP_6, MCEH_8)) ^

116 (EXISTS MT_9, MTP_10, MT_11: Message |

117 ({MT_9, MTP_10, MT_11} SUBSETEQ msgs() ^

118 sig(MT_9) = joinPool() ^

119 sig(MTP_10) = join() ^

120 sig(MT_11) = notify(NewFollower) ^

121 c(name(lifeline(sender(MT_9)))) = T_1 ^

122 c(name(lifeline(receiver(MT_9)))) = T_1 ^

123 c(name(lifeline(sender(MTP_10)))) = T_1 ^

124 c(name(lifeline(receiver(MTP_10)))) = TP ^

125 c(name(lifeline(sender(MT_11)))) = TP ^

126 c(name(lifeline(receiver(MT_11)))) = T_1) =>

127 (precedes(MCEH_8, MT_9) ^

21

+read()+process()

SyncTask

+isert()+remove()

MessageQueue

+enqueue()+notify()

AsyncTask

+interrupt()+read()+process()

ExternalEventSource

1..*

1..*

1..*

1..*

1..*

1..*

Figure 13: The Half-Sync/Half-Async pattern class diagram (revised from [SC95,BHS07])

128 precedes(MT_9, MTP_10) ^

129 calls(joinPool(), join()) ^

130 precedes(MTP_10, MT_11))

131 )))

Listing 5: The Leader/Followers pattern specification in PSL

2.6 The Half-Sync/Half-Async Pattern

Figure 13 and Figure 14 show the class diagram and sequence diagrams representingthis pattern, respectively.

Listing 6 demonstrates the Half-Sync/Half-Async pattern PSL code.

1 patternName:

2 HalfSync_HalfAsync

3

4 components:

5 {MessageQueue, SyncTask, AsyncTask, ExternalEventSource} SUBSETEQ classes();

6 {read(), process()} SUBSETEQ opers(SyncTask);

7 {insert(), remove()} SUBSETEQ opers(MessageQueue);

8 {enqueue(), notify()} SUBSETEQ opers(AsyncTask);

9 {interrupt(), read(), process()} SUBSETEQ opers(ExternalEventSource);

22

SyncTaskMessageQueue

AsyncTaskExternalEvent Source

process()

read(msg)

enqueue()

process()

read(msg)

notify(event)

interrupt()

Figure 14: The Half-Sync/Half-Async pattern sequence diagram (revised from [SC95,BHS07])

10

11 staticConditions:

12

13 associates(ExternalEventSource, AsyncTask) ^

14 associates(AsyncTask, MessageQueue) ^

15 associates(MessageQueue, SyncTask)

16

17 dynamicConditions:

18

19 (FORALL M: Message; EES, AT, MQ, ST: Class |

20 (M IN msgs() ^ {EES, AT, MQ, ST} SUBSETEQ classes() ^

21 name(EES) = ExternalEventSource ^

22 name(AT) = AsyncTask ^

23 name(MQ) = MessageQueue ^

24 name(ST) = SyncTask) @

25 (c(name(lifeline(receiver(M)))) = EES ^

26 sig(M) = interrupt())

27 =>

28 ((EXISTS MAT_2: Message |

29 (MAT_2 IN msgs() ^

30 sig(MAT_2) = notify(Event) ^

31 c(name(lifeline(sender(MAT_2)))) = EES ^

32 c(name(lifeline(receiver(MAT_2)))) = AT) =>

33 (precedes(M, MAT_2) ^

34 calls(interrupt(), notify(Event)))) ^

35 (EXISTS MEES_3: Message |

23

36 (MEES_3 IN msgs() ^

37 sig(MEES_3) = read(Msg) ^

38 c(name(lifeline(sender(MEES_3)))) = AT ^

39 c(name(lifeline(receiver(MEES_3)))) = EES) =>

40 precedes(MAT_2, MEES_3)) ^

41 (EXISTS MAT_4, MQ_5: Message |

42 ({MAT_4, MQ_5} SUBSETEQ msgs() ^

43 sig(MAT_4) = process() ^ sig(MQ_5) = enqueue() ^

44 c(name(lifeline(sender(MAT_4)))) = AT ^

45 c(name(lifeline(receiver(MAT_4)))) = AT ^

46 c(name(lifeline(sender(MQ_5)))) = AT ^

47 c(name(lifeline(receiver(MQ_5)))) = MQ) =>

48 (precedes(MEES_3, MAT_4) ^

49 precedes(MAT_4, MQ_5))) ^

50 (EXISTS MQ_6, MST_7: Message |

51 ({MQ_6, MST_7} SUBSETEQ msgs() ^

52 sig(MQ_6) = read(Msg) ^ sig(MQ_5) = process() ^

53 c(name(lifeline(sender(MQ_6)))) = ST ^

54 c(name(lifeline(receiver(MQ_6)))) = MQ ^

55 c(name(lifeline(sender(MST_7)))) = ST ^

56 c(name(lifeline(receiver(MST_7)))) = ST) =>

57 (precedes(MQ_5, MQ_6) ^

58 precedes(MQ_6, MST_7)))

59 ))

Listing 6: The Half-Sync/Half-Async pattern specification in PSL

2.7 The Monitor Object Pattern

Figure 15 and Figure 16 show the class diagram and sequence diagrams representingthis pattern, respectively.

Listing 7 demonstrates the Monitor Object pattern PSL code.

1 patternName:

2 MonitorObject

3

4 components:

5

6 {Monitor, Client, Synchronized, Lock, Condition} SUBSETEQ classes();

7 {invoke(), sleep(), resume()} SUBSETEQ opers(Client);

8 {wait(), notify()} SUBSETEQ opers(Condition);

9 {acquire(), release()} SUBSETEQ opers(Lock);

10 method() IN opers(Synchronized);

11 doWord() IN opers(Monitor)

12

13 staticConditions:

24

+doWork()

Monitor

+invoke()+sleep()+resume()

Client

+acquire()+release()

Lock

+wait()+notify()

Condition

+method()

Synchronized

1..*

methods 1 conditions

lock

*

1

1

1

11..*

Figure 15: The Monitor Object pattern class diagram (revised from [Sch00, BHS07])

14

15 depends(Client, Synchronized) ^

16 depends(Synchronized, Lock) ^

17 associates(Monitor, Lock) ^

18 associates(Client, Monitor) ^

19 composes(Monitor, Synchronized) ^

20 composes(Monitor, Condition)

21

22 dynamicConditions:

23

24 (FORALL M: Message; T_1, T_2, S, L, M, Cond: Class |

25 (M IN msgs() ^

26 {T_1, T_2, S, L, M, Cond} SUBSETEQ classes() ^

27 name(T_1) = Client ^

28 name(T_2) = Client ^

29 name(S) = Synchronized ^

30 name(L) = Lock ^

31 name(M) = Monitor ^

32 name(Cond) = Condition) @

33 (c(name(lifeline(sender(M)))) = T_1 ^

34 c(name(lifeline(receiver(M)))) = T_1 ^

35 sig(M) = interrupt())

36 =>

37 ((EXISTS MS_2: Message |

38 (MS_2 IN msgs() ^

39 sig(MS_2) = method() ^

40 name(c(name(lifeline(sender(MS_2))))) = T_1 ^

41 name(c(name(lifeline(receiver(MS_2))))) = S) =>

42 (precedes(M, MS_2) ^

43 calls(invoke(), method()))) ^

44 (EXISTS ML_3, MM_4: Message |

25

T2 : Client ConditionMonitorLockSynchronizedT1 : Client

return()release()

doWork()

acquire()

resume method()

resume()

return()

method()

release()notify()

doWork()

acquire()

sleep()release()

wait()

invoke()

doWork()

acquire()method()

invoke()

Figure 16: The Monitor Object pattern sequence diagram (revised from [Sch00,BHS07])

26

45 ({ML_3, MM_4} SUBSETEQ msgs() ^

46 sig(ML_3) = acquire() ^ sig(MM_4) = doWork() ^

47 c(name(lifeline(sender(ML_3)))) = S ^

48 c(name(lifeline(receiver(ML_3)))) = S ^

49 c(name(lifeline(sender(MM_4)))) = L ^

50 c(name(lifeline(receiver(MM_4)))) = M) =>

51 (precedes(MS_2, ML_3) ^

52 precedes(ML_3, MM_4))) ^

53 (FORALL MC_5: Message |

54 (MC_5 IN msgs() ^

55 sig(MC_5) = wait() ^

56 c(name(lifeline(sender(MC_5)))) = M ^

57 c(name(lifeline(receiver(MC_5)))) = Cond) @

58 (precedes(MM_4, MC_5) ^

59 calls(doWork(), wait()))

60 =>

61 ((EXISTS ML_6, MT1_7: Message |

62 ({ML_6, MT1_7} SUBSETEQ msgs() ^

63 sig(ML_6) = release() ^

64 sig(MT1_7) = sleep() ^

65 c(name(lifeline(sender(ML_6)))) = Cond ^

66 c(name(lifeline(receiver(ML_6)))) = L ^

67 c(name(lifeline(sender(MT1_7)))) = Cond ^

68 c(name(lifeline(receiver(MT1_7)))) = T_1) =>

69 (precedes(MC_5, ML_6) ^

70 calls(wait(), sleep()) ^

71 precedes(ML_6, MT1_7))) ^

72 (EXISTS MT2_8, MS_9: Message |

73 ({MT2_8, MS_9} SUBSETEQ msgs() ^

74 sig(MT2_8) = invoke() ^

75 sig(MS_9) = method() ^

76 c(name(lifeline(sender(MT2_8)))) = T_2 ^

77 c(name(lifeline(receiver(MT2_8)))) = T_2 ^

78 c(name(lifeline(sender(MS_9)))) = T_2 ^

79 c(name(lifeline(receiver(MS_9)))) = S) @

80 (precedes(ML_6, MT2_8) ^

81 precedes(MT2_8, MS_9) ^

82 calls(invoke(), method()))

83 =>

84 ((EXISTS ML_10, MM_11,ML_12: Message |

85 ({ML_10, MM_11, ML_12} SUBSETEQ msgs() ^

86 sig(ML_10) = acquire() ^

87 sig(MM_11) = doWork() ^

88 sig(ML_12) = release() ^

89 c(name(lifeline(sender(ML_10)))) = S ^

90 c(name(lifeline(receiver(ML_10)))) = L ^

91 c(name(lifeline(sender(MM_11)))) = L ^

92 c(name(lifeline(receiver(MM_11)))) = M ^

27

+createProductA()+createProductB()

<<Interface>>AbstractFactory

+createProductA()+createProduct(B)

ConcreteFactory2

<<Interface>>AbstractProductA

ProductA1

<<Interface>>AbstractProductB

ProductB1

Client

+createProductA()+createProductB()

ConcreteFactory1

ProductA2ProductB2

Figure 17: The Abstract Factory pattern class diagram [GHJV94]

93 c(name(lifeline(sender(ML_12)))) = M ^

94 c(name(lifeline(receiver(ML_12)))) = L) =>

95 (precedes(MS_9, ML_10) ^

96 precedes(ML_10, MM_11) ^

97 precedes(MM_11, ML_12) ^

98 calls(doWork(), release()))) ^

99 (EXISTS MC_13, CT1_14: Message |

100 ({MC_13, CT1_14} SUBSETEQ msgs() ^

101 sig(MC_13) = notify() ^

102 sig(CT1_14) = resume() ^

103 c(name(lifeline(sender(MC_13)))) = M ^

104 c(name(lifeline(receiver(MC_13)))) = Cond ^

105 c(name(lifeline(sender(CT1_14)))) = Cond ^

106 c(name(lifeline(receiver(CT1_14)))) = T_1) =>

107 (precedes(ML_12, MC_13) ^

108 precedes(MC_13, CT1_14) ^

109 calls(notify(),resume())))

110 ))))))

Listing 7: The Monitor Object pattern specification in PSL

2.8 The Abstract Factory Pattern

Figure 17 shows the class diagram representing this pattern that provide interfacesfor creating two product types, i.e., ProductA and ProductB.

28

Listing 8 demonstrates the Abstract Factory pattern PSL code.

1 patternName:

2 AbstractFactory

3

4 components:

5

6 {AbstractFactory, Client, ConcreteFactory,

7 AbstractProduct, Product} SUBSETEQ classes();

8 createProduct() IN opers(AbstractFactory);

9 createProduct() IN opers(ConcreteFactory);

10

11 staticConditions:

12

13 isInterface(AbstractFactory) ^

14 isInterface(AbstractProduct) ^

15 realizes(ConcreteFactory, AbstractFactory) ^

16 realizes(Product, AbstractProduct) ^

17 depends(Client, AbstractFactory) ^

18 depends(ConcreteFactory, Product) ^

19

20 /*

21 * For each interface AbstractFactory which references a Client

22 * there must be two ConcreteFactory, two AbstractProduct, and four Product

23 * so that ConcreteFactories realizes AbstractFactories;

24 * Products which must be concrete and unique realizes AbstractProducts and

25 * there must be dependencies from the ConcreteFactories to the Products

26 */

27 FORALL AF: AbstractFactory; C: Client @ (isInterface(AF) ^

28 depends(C, AF))

29 =>

30 (EXISTS CF1, CF2: ConcreteFactory; AP1, AP2: AbstractProduct;

31 PA1, PA2, PB1, PB2: Product |

32 (CF1 <> CF2 ^ AP1 <> AP2 ^

33 ~isAbstract(CF1) ^

34 ~isAbstract(CF2) ^

35 isAbstract(AP1) ^

36 isAbstract(AP2)) @

37 (depends(C, AP1) ^ depends(C, AP1) ^

38 realizes(CF1, AF) ^

39 realizes(CF2, AF) ^

40 realizes(PA1, AP1) ^

41 realizes(PA2, AP1) ^

42 realizes(PB1, AP2) ^

43 realizes(PB2, AP2))

44 => (depends(CF1, PA1) ^ depends(CF1, PB1) ^

45 depends(CF2, PA2) ^ depends(CF2, PB2) ^

46 ~isAbstract(PA1) ^ ~isAbstract(PA2) ^

47 ~isAbstract(PB1) ^ ~isAbstract(PB2) ^

29

+insert()+remove()

ComponentRepository

+configScript()

ComponentConfigurator

Component+init()+fini()+suspend()+resume()+info()

+run()

ConceteComponentA

+run()

ConcreteComponentB

*components

Figure 18: The Component Configurator pattern class diagram (revised from [JS97,SSRB00, BHS07])

48 PA1 <> PA2 ^ PB1 <> PB2))

49

50 dynamicConditions:

Listing 8: The Abstract Factory pattern specification in PSL

2.9 The Component Configurator Pattern

Figure 18 and Figure 19 show the class diagram and sequence diagrams representingthis pattern, respectively. Here, the dynamic configuration is illustrated by the twoconfigurable components on the diagrams, i.e., ConcreteComponentA and Concrete-ComponentB.

Listing 9 demonstrates the Component Configurator pattern PSL code.

1 patternName:

2 ComponentConfigurator

3

4 components:

5

6 {ComponentConfigurator, ComponentRepository, Component,

7 ConcreteComponent} SUBSETEQ classes();

8 {insert(), remove()} SUBSETEQ opers(ComponentRepository);

9 {init(), fini(), suspend(), resume(), info()} SUBSETEQ opers(Component);

10 configScript() IN opers(ComponentConfigurator);

11 run() IN opers(ConcreteComponent);

12

13 staticConditions:

14

15 isAbstract(Component) ^

16 depends(ComponentConfigurator, ComponentRepository) ^

17 aggregates(ComponentRepository, Component) ^

30

ComponentRepository

ConcreteComponentB

ConcreteComponentA

ComponentConfigurator

configScript()

remove(ConcreteComponentB)

fini()

remove(ConcreteComponentA)

fini()

run()run()

insert(ConcreteComponentB)

init()

insert(ConcreteComponentA)

init()

Figure 19: The Component Configurator pattern sequence diagram (revised from[JS97, SSRB00, BHS07])

31

18 inherits(ConcreteComponent, Component) ^

19

20 // Each abstract component must be inherited by at least two non-abstract ConcreteComponents

21 FORALL C: Component @ isAbstract(C) =>

22 (EXISTS CCA, CCB: ConcreteComponent =>

23 (CCA <> CCB ^

24 ~isAbstract(CCA) ^

25 ~isAbstract(CCB) ^

26 inherits(CCA, C) ^

27 inherits(CCB, C)))

28

29 dynamicConditions:

30

31 (FORALL M: Message; CC, ConcreteC, CR: Class |

32 (M IN msgs() ^

33 {CC, ConcreteC, CR} SUBSETEQ classes() ^

34 name(CC) = ComponentConfigurator ^

35 name(ConcreteC) = ConcreteComponent ^

36 name(CR) = ComponentRepository) @

37 (c(name(lifeline(sender(M)))) = CC ^

38 c(name(lifeline(receiver(M)))) = CC ^

39 sig(M) = configScript())

40 =>

41 ((EXISTS MCC: Message |

42 (MCC IN msgs() ^

43 sig(MCC) = init() ^

44 c(name(lifeline(sender(MCC)))) = CC ^

45 c(name(lifeline(receiver(MCC)))) = ConcreteC) =>

46 (precedes(M, ConcreteC) ^

47 calls(configScript(), init()))) ^

48 (EXISTS MCR: Message |

49 (MCR IN msgs() ^

50 sig(MCR) = insert(ConcreteComponent) ^

51 c(name(lifeline(sender(MCR)))) = CC ^

52 c(name(lifeline(receiver(MCR)))) = CR) =>

53 precedes(ConcreteC, MCR)))) ^

54 (FORALL M: Message; ConcreteC: Class |

55 (M IN msgs() ^

56 CC_A IN classes() ^

57 name(ConcreteC) = ConcreteComponent) @

58 (c(name(lifeline(receiver(M)))) = ConcreteC ^

59 sig(M) = run())

60 =>

61 (EXISTS MCR: Message; CC, CR: Class |

62 (MCR IN msgs() ^

63 {CC, CR} SUBSETEQ classes() ^

64 name(CC) = ComponentConfigurator ^

65 name(CR) = ComponentRepository ^

32

66 sig(MCR) = insert(ConcreteComponent) ^

67 c(name(lifeline(sender(MCR)))) = CC ^

68 c(name(lifeline(receiver(MCR)))) = CR) =>

69 precedes(MCR, M))) ^

70 (FORALL M: Message; CC, ConcreteC, CR: Class |

71 (M IN msgs() ^

72 {CC, ConcreteC, CR} SUBSETEQ classes() ^

73 name(CC) = ComponentConfigurator ^

74 name(CC_A) = ConcreteComponent ^

75 name(CR) = ComponentRepository) @

76 (c(name(lifeline(sender(M)))) = CC ^

77 c(name(lifeline(receiver(M)))) = ConcreteC ^

78 sig(M) = fini())

79 =>

80 (EXISTS MCR: Message |

81 (MCR IN msgs() ^

82 sig(MCR) = remove(ConcreteComponent) ^

83 c(name(lifeline(sender(MCR)))) = CC ^

84 c(name(lifeline(receiver(MCR)))) = CR) =>

85 precedes(M, MCR)))

Listing 9: The Component Configurator pattern specification in PSL

3 The PLSL parser in action

To specify a given PL, we use the PLSL language. Figure 20 displays the PLSL Editorusage in practice.

A The PSL source code in Xtext

This section presents the PSL parser source code in Xtext.

1 /* The name of produced grammar model with the .psl extension

2 mixed with the Terminals library grammar */

3 grammar ir.ui.se.mdserg.xtext.PSL

4 with org.eclipse.xtext.common.Terminals

5 hidden (WS) // terminal WS : (’ ’|’\t’|’\r’|’\n’)+;

6

7 /* PSL is the name of the generated ecore model root EPackage.

8 http://www.ui.ir/se/mdserg/xtext/pattern/PSL

9 is the nsURI of the generated package */

10 generate pSL "http://www.ui.ir/se/mdserg/xtext/PSL"

11

12 import "http://www.eclipse.org/emf/2002/Ecore" as ecore

33

Figure 20: The PLSL Editor

13

14 Specification:

15 {Specification}

16 (comment += Comment)*

17 ’patternName:’ name = CID

18 ’components:’ (components += Declaration ’;’?)+

19 ’staticConditions:’ (staticConditions += StaticCondition ’^’?)*

20 ’dynamicConditions:’ (dynamicConditions += DynamicCondition ’^’?)*

21 ;

22

23 Declaration:

24 comment = Comment? (si = SetInclusion | sm = SetMembership)

25 ;

26

27 SetInclusion:

28 ’{’ head = memberName (comma +=’,’ tail += memberName)* ’}’

29 subset = ’SUBSETEQ’ set = Type

30 ;

31

32 SetMembership:

33 member = memberName in = ’IN’ set = Type

34 ;

35

36 // member name can be a Classifier ID (CID),

37 // function ID(param1[()], ...), or attribute ID (FUNCID)

34

38 memberName:

39 CID | FUNCID (’(’ ((CID | FUNCID (’(’ ’)’)?) ’,’?)* ’)’)?

40 ;

41

42 Type:

43 {Type} (basic = BasicType |

44 fi = FuncInclusion |

45 ps = ’P(’ type = Type ’)’ |

46 cid = CID

47 )

48 ;

49

50 BasicType:

51 ’Boolean’ | ’Integer’ | ’String’ | ’Value’ | ’Class’ | ’Interface’ |

52 ’Operation’ | ’Property’ | ’Lifeline’ | ’Message’ | ’Parameter’

53 ;

54

55 DirectionKind:

56 ’in’ | ’inout’ | ’out’ | ’return’

57 ;

58

59 VisibilityKind:

60 ’public’ | ’private’ | ’protected’ | ’package’

61 ;

62

63 StaticCondition:

64 {StaticCondition} comment = Comment? scond = Formula

65 ;

66

67 DynamicCondition:

68 {DynamicCondition} comment = Comment? dcond = Formula

69 ;

70

71 Boolean:

72 ’true’ | ’false’

73 ;

74

75 FuncInclusion:

76 f = FunName ’(’ (params += Param ’,’?)* ’)’

77 (op = CompOp value = RangeType)?

78 ;

79

80 FunName:

81 Reserved | FUNCID

82 ;

83

84 Reserved:

85 ’calls’ | ’precedes’ | ’subs’ | ’name’ | ’c’ | ’lifeline’ |

35

86 ’sig’ | ’msgs’ | ’sender’ | ’receiver’ | ’classes’ |

87 ’opers’ | ’attrs’ | ’params’ | ’associates’ | ’composes’ | ’depends’ |

88 ’aggregates’ | ’inherits’ | ’realizes’ |

89 ’isInterface’ | ’isAbstract’ | ’isFinal’ |

90 ’isAssocClass’ | ’isCDR’ | // A given Classifier’s Properties

91 ’visibility’ | ’type’ | ’mult’ | ’default’ |

92 ’isDerived’ | ’isReadOnly’ | ’isDerivedUnion’ |

93 ’lower’ | ’upper’ | // A given Property’s Features

94 ’isLeaf’ | ’isStatic’ | ’isQuery’ | // A given Operation’s properties

95 ’direction’ // A given Parameter’s direction kind

96 ;

97

98 Param:

99 cid = (CID | FUNCID)

100 ("::"

101 (fi = (CID | FUNCID) ’(’ ’)’ | aid = (CID | FUNCID))

102 ("#" paramid = (CID | FUNCID))?)? | FuncInclusion

103 ;

104

105 RangeType:

106 {RangeType} (bool = Boolean |

107 vk = VisibilityKind |

108 dk = DirectionKind |

109 int = INT | // specific to the multiplicity’s lower and upper values

110 star = ’*’ | // for specifying the multiplicity’s infinite bound

111 cid = CID | // represents string type

112 basic = BasicType | // for the definition of property types

113 fi = FuncInclusion

114 )

115 ;

116

117 Formula:

118 neg = UnaryConn?

119 (sf = SimpleFormula |

120 qf = QuantFormula | lp = ’(’ mf = MixedFormula rp = ’)’

121 )

122 ;

123

124 QuantFormula:

125 q = Quantifier types = QTypes

126 (suchThat = SuchThat st = QFormula)?

127 (atSign = AtSign at = QFormula)?

128 conseq = ConseqConn consequent = QFormula

129 ;

130

131 QFormula:

132 f = Formula

133 ;

36

134

135 MixedFormula:

136 Formula ({MixedFormula.lhs = current} ((or += ’v’ orRHS += Formula)* |

137 (and += ’^’ andRHS += Formula)*

138 ))

139 ;

140

141 Quantifier:

142 forall = ’FORALL’ | exists = ’EXISTS’

143 ;

144

145 SuchThat:

146 ’|’

147 ;

148

149 AtSign:

150 ’@’

151 ;

152

153 ConseqConn:

154 ’=>’ | ’<=>’

155 ;

156

157 QTypes:

158 head = VarType (semicolon += ’;’ tail += VarType)*

159 ;

160

161 VarType:

162 header = CID (colon += ’,’ trailer += CID)* ’:’ type = Type

163 ;

164

165 SimpleFormula:

166 l = LHSOperand op = CompOp r = RHSOperand |

167 si = SetInclusion |

168 sm = SetMembership |

169 fi = FuncInclusion

170 ;

171

172 RHSOperand:

173 cid = CID | fi = FUNCID | bool = Boolean | int = INT | star = ’*’

174 ;

175

176 LHSOperand:

177 cid = CID

178 ;

179

180 UnaryConn:

181 ’~’

37

182 ;

183

184 CompOp:

185 ’<’ | ’<=’ | ’>’ | ’>=’ | ’=’ | ’<>’

186 ;

187

188 terminal CID returns ecore::EString:

189 (’A’..’Z’)(’a’..’z’ | ’A’..’Z’ | ’0’..’9’ | ’_’ )*

190 ;

191

192 terminal FUNCID returns ecore::EString:

193 (’a’..’z’)(’a’..’z’ | ’A’..’Z’ | ’0’..’9’ | ’_’ )*

194 ;

195

196 terminal INT returns ecore::EInt :

197 (’0’..’9’)+;

198

199 Comment:

200 SL_COMMENT | ML_COMMENT

201 ;

202

203 terminal SL_COMMENT:

204 ’//’ !(’\n’|’\r’)* (’\r’ | ’\n’)+

205 ;

206

207 terminal ML_COMMENT:

208 ’/*’ -> ’*/’

209 ;

Listing 10: The PSL’s parser generation code in Xtext

B The PLSL source code in Xtext

This section presents the PLSL parser source code in Xtext.

1 // This parser is used to extract a given pattern language

2 // patterns, relationships and consequences of applying patterns

3 // the extension PLSL is an abbreviation for

4 // the Pattern Language Specification Language

5

6 grammar ir.ui.mdserg.xtext.PLSL

7 with org.eclipse.xtext.common.Terminals

8 hidden (WS) // terminal WS : (’ ’|’\t’|’\r’|’\n’)+;

9

10 generate pLSL "http://www.ui.ir/mdserg/xtext/PLSL"

11

38

12 import "http://www.eclipse.org/emf/2002/Ecore" as ecore

13

14 PatternLanguage:

15 Comment? ’PatternLanguageName:’ name = PID

16 Comment? ’Patterns:’ ’{’ head = Pattern (’,’ tail += Pattern)* ’}’

17 Comment? ’InitPattern:’ initPattern = Pattern

18 (Comment? ’Relationships:’ relationships += Relationship*)?

19 (Comment? ’ConseqsFunction:’ consequnces += Consequence*)?

20 ;

21

22 Pattern:

23 pid = PID

24 ;

25

26 Relationship:

27 first = Pattern rel = Relation second = Pattern

28 ;

29

30 Relation:

31 relationshipKind = (’uses’ | ’refines’ | ’conflicts’ | ’competes’)

32 ;

33

34 Consequence:

35 ’(’ first = Pattern ’,’ second = Pattern ’)’ ’->’

36 benefits = Benefits ’,’ liabilities = Liabilities

37 ;

38

39 Liabilities:

40 {Liabilities} ’{’ (lHead = Liability (’,’ lTail += Liability)*)? ’}’

41 ;

42

43 Benefits:

44 {Benefits} ’{’ (bHead = Benefit (’,’ bTail += Benefit)*)? ’}’

45 ;

46

47 Benefit:

48 Goal

49 ;

50

51 Liability:

52 Goal

53 ;

54

55 Goal:

56 goal = (’simplicity’ | ’modularity’ | ’encapsulation’ | ’portability’ |

57 ’testability’ | ’stability’ |

58 ’flexibility’ | ’performance’ | ’transparency’ |

59 ’predictability’ | ’applicability’ | ’scalability’ | ’availability’ |

39

60 ’deadlock’ | ’extendibility’ | ’lowcoupling’ | ’complexity’)

61 ;

62

63 terminal PID returns ecore::EString:

64 (’A’..’Z’)(’a’..’z’ | ’A’..’Z’ | ’0’..’9’ | ’_’ )*

65 ;

66

67 Comment:

68 SL_COMMENT | ML_COMMENT

69 ;

70

71 terminal SL_COMMENT:

72 ’//’ !(’\n’|’\r’)* (’\r’ | ’\n’)+

73 ;

74

75 terminal ML_COMMENT:

76 ’/*’ -> ’*/’

77 ;

Listing 11: The PLSL’s parser generating code in Xtext

References

[BCW12] Marco Brambilla, Jordi Cabot, and Manuel Wimmer. Model-driven soft-ware engineering in practice. Synthesis Lectures on Software Engineering,1(1):1–182, 2012. 3

[Bet13] Lorenzo Bettini. Implementing Domain-Specific Languages with Xtext andXtend. Packt Publishing Ltd, 2013. 2

[BHS07] Frank Buschmann, Kevlin Henney, and Douglas C Schmidt. Pattern-Oriented Software Architecture: A Pattern Language for Distributed Com-puting, volume 4. John Wiley & Sons, 2007. 4, 8, 9, 10, 12, 13, 14, 18,19, 22, 23, 25, 26, 30, 31

[BMR+96] Frank Bushmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, andMichael Stal. Pattern-oriented software architecture: A system of patterns,volume 1. John Wiley & Sons, 1996. 4, 5

[EB10] Moritz Eysholdt and Heiko Behrens. Xtext: implement your languagefaster than the quick and dirty way. In International conference compan-ion on Object oriented programming systems languages and applicationscompanion, 2010. OOPSLA’10, pages 307–309, New York, USA, 2010.ACM. 2

40

[GHJV94] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. De-sign Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional, 1st edition, 1994. 28

[Gro09] Richard C Gronback. Eclipse modeling project: a domain-specific language(DSL) toolkit. Pearson Education, 2009. 2, 3

[JB06] Frederic Jouault and Jean Bezivin. KM3: a DSL for metamodel specifica-tion. In Roberto Gorrieri and Heike Wehrheim, editors, Formal Methodsfor Open Object-Based Distributed Systems, volume 4037 of Lecture Notesin Computer Science, pages 171–185. Springer, 2006. 3

[JS97] Prashant Jain and Douglas C Schmidt. Dynamically configuring com-munication services with the service configurator pattern. C++ Report,9(6):29–42, 1997. 30, 31

[PKP14] Richard F Paige, Dimitrios S Kolovos, and Fiona AC Polack. A tutorialon metamodelling for grammar researchers. Science of Computer Pro-gramming, 96:396–416, 2014. 3

[RZ15] Alireza Rouhi and Bahman Zamani. An Xtext Generated Parser to Vali-date the Revised and Extended GEBNF Applications. Technical ReportUI-SE-MDSERG-2015-03, Model-Driven Software Engineering ResearchGroup, University of Isfahan, Isfahan, Iran, 23 October 2015. 3

[RZ16] Alireza Rouhi and Bahman Zamani. Towards a formal model of patternsand pattern languages. Information and Software Technology, 79:1–16,2016. 2, 3

[SBMP08] Dave Steinberg, Frank Budinsky, Ed Merks, and Marcelo Paternostro.EMF: eclipse modeling framework. Pearson Education, 2008. 2, 3

[SC95] Douglas C Schmidt and Charles D Cranor. Half-sync/half-async-an ar-chitectural pattern for efficient and well-structured concurrent i/o. InProceedings of the 2nd Annual Conference on the Pattern Languages ofPrograms. Citeseer, 1995. 22, 23

[Sch95] Douglas C Schmidt. Reactor: An object behavioral pattern for concurrentevent demultiplexing and dispatching. 1995. 9, 10

[Sch96] Douglas C Schmidt. Acceptor and connector: A family of object cre-ational patterns for initializing communication services. In Proceedingsof the European Pattern Language of Programs (EuroPLoP) conference.Citeseer, 1996. 12, 13, 14

41

[Sch99] Douglas C Schmidt. Wrapper facade-a structural pattern for encapsulat-ing functions within classes. 1999. 8, 9

[Sch00] Douglas C Schmidt. Monitor object–an object behavior pattern for con-current programming. C++ Report, 12, 2000. 25, 26

[SOK+00] Douglas C Schmidt, Carlos O’Ryan, Michael Kircher, Irfan Pyarali, andFrank Buschmann. Leader/followers. In University of Washington.http://www.cs.wustl.edu/˜schmidt/PDF/lf.pdf. Citeseer, 2000. 18, 19

[SSRB00] Douglas C Schmidt, Michael Stal, Hans Rohnert, and Frank Buschmann.Pattern-Oriented Software Architecture, Patterns for Concurrent and Net-worked Objects, volume 2. John Wiley & Sons, 2000. 30, 31

42