Easy Language Extension With Meta-Aspectj Domain-specific languages hold the potential of automating the software development process . Nevertheless , the adop-tion of a domain-specific language is hindered by the difficulty of transitioning to different language syntax and employing a separate translator in the software build process . We present a methodology that simplifies the development and deployment of small language extensions , in the context of Java . The main language design principle is that of language extension through unobtrusive annotations . The main language implementation idea is to express the language as a generator of customized AspectJ aspects , using our Meta-AspectJ tool . The advantages of the approach are twofold . First , the tool integrates into an existing software application much as a regular API or library , instead of as a language extension . This means that the programmer can remove the language extension at any point and choose to implement the required functionality by hand without needing to rewrite the client code . Second , a mature language implementation is easy to achieve with little effort since AspectJ takes care of the low-level issues of interfacing with the base Java language . D. 1.2 -LSB- Programming Techniques -RSB- : Automatic Programming ; D. 2.13 -LSB- Software Engineering -RSB- : Reusable Software ; D. 3.3 -LSB- Programming Languages -RSB- : Language Constructs and Features domain-specific languages , language extensions The idea of extensible languages has fascinated programmers for many decades , as evident by the extensibility fea This material is based upon work supported by the National Science Foundation under Grants No . CCR-0220248 and CCR-0238289 . Copyright is held by the author/owner . ICSE ' 06 , May 20 28 , 2006 , Shanghai , China . ACM 1-59593-085-X / 06/0005 . tures in languages as old as Lisp . From a Software Engineering standpoint , the main advantages of expressing a concept as a language feature , as opposed to a library API , are in terms of conciseness , safety , and performance . A language feature allows expressing the programmer 's intent much more concisely -- in contrast , libraries are limited to a function - or method-call syntax . A language feature also allow better static error checking -- a library can only check the static types of arguments of a function call against the declared types of the formals . Finally , a language feature can take advantage of context information and employ an optimized implementation , while a library routine can not be customized according to its uses . Despite these advantages , there are excellent reasons why full language extensibility is undesirable . Changing the syntax and semantics of a programming language is confusing and can lead to incomprehensible code . Furthermore , programming languages are complex entities , designed to provide a small number of features but allow them to be combined as generally as possible . A new feature can either increase the complexity of the language implementation significantly -LRB- because of interactions with all existing features -RRB- , or will need to be limited in its interactions , which is a bad language design principle that leads to single-use features and design bloat . In past work -LSB- 3 -RSB- , we have advocated expressing small language extensions purely through unobtrusive annotations . Indeed , the introduction of user-defined annotations in mainstream programming languages , such as C# and Java , has allowed specialized language extensions -LRB- e.g. , for distributed computing , persistence , or real-time programming -RRB- to be added without changing the base syntax . We believe that the approach of limited language extension through annotations meshes very well with an implementation technique that uses our Meta-AspectJ -LRB- MAJ -RRB- tool -LSB- 4 -RSB- to express the semantics of the language extension . Specifically , MAJ is a language that allows writing programs that generate aspects in the AspectJ language -LSB- 1 -RSB- . The programmer can easily express an extension to the Java language as a program that : a -RRB- reads annotations and type information from an existing program using Java reflection ; b -RRB- outputs a customized AspectJ aspect that transforms the original program according to the information in the annotation ; c -RRB- executes the generated aspect by using the standard AspectJ compiler . In other words , our approach uses the AspectJ language as a compiler back-end . AspectJ code is not written by the application programmer but generated by the language 865 extension , for the sole purpose of expressing program transformations easily and generally . This is appropriate , as AspectJ embodies the Aspect-Oriented Programming -LSB- 2 -RSB- philosophy of expressing program enhancements orthogonally and independently of the original source code . Our approach has the advantage of simplifying the implementation of the language extension significantly , without encouraging undisciplined language extension -LRB- since the only extensions allowed are through annotations -RRB- . Specifically , the approach leverages the engineering sophistication of the AspectJ compiler implementation and its provisions for dealing correctly with different Java language features . If a programmer were to replicate the same effort by hand , she would likely need to reproduce much of the AspectJ compiler complexity . The purpose of this paper is to support the idea of implementing small language extensions as programs that produce aspects . We have recently implemented a number of such small extensions to Java and they all exhibit a striking simplicity . Specifically , we did not have to implement -LRB- or extend -RRB- a Java parser , we did not need to deal with syntax tree pattern matching and transformation , and we did not need to provide special handling for many Java complexities . The combined annotations-MAJ approach ensured that our small language extensions were implementable in a few hundreds of lines of code , without sacrificing generality in their conditions of use . We discuss two such extensions in detail , after first introducing the MAJ language . MAJ is an extension of Java that allows writing programs that generate AspectJ source code . MAJ offers two operators for creating AspectJ code fragments : ` -LSB- ... -RSB- -LRB- `` quote '' -RRB- and # -LSB- ... -RSB- -LRB- `` unquote '' -RRB- . The quote operator creates representations of AspectJ code fragments . Parts of these representations can be variable and are desig-nated by the unquote operator -LRB- instances of unquote can only occur inside a quoted code fragment -RRB- . For example , the value of the MAJ expression ` -LSB- call -LRB- * * -LRB- . . -RRB- -RRB- -RSB- is a data structure that represents the abstract syntax tree for the fragment of AspectJ code call -LRB- * * -LRB- . . -RRB- -RRB- . Similarly , the MAJ expression ` -LSB- ! within -LRB- #className -RRB- -RSB- is a quoted pattern with an unquoted part . Its value depends on the value of the variable className . If , for instance , className holds the identifier `` SomeClass '' , the value of ` -LSB- ! within -LRB- #className -RRB- -RSB- is the abstract syntax tree for the expression ! within -LRB- SomeClass -RRB- . MAJ also introduces a new keyword infer that can be used in place of a type name when a new variable is being declared and initialized to a quoted expression . For example , we can write : infer pct1 = ` -LSB- call -LRB- * * -LRB- . . -RRB- -RRB- -RSB- ; This declares a variable pct1 that can be used just like any other program variable . For instance , we can unquote it : infer adv1 = ` -LSB- void around -LRB- -RRB- : #pct1 -LCB- -RCB- -RSB- ; This creates the abstract syntax tree for a piece of AspectJ code defining -LRB- empty -RRB- advice for a pointcut . Of course , since AspectJ is an extension of Java , any regular Java program fragment can be generated using MAJ. We can now see a full MAJ method that generates a trivial but complete AspectJ file : void generateTrivialLogging -LRB- String classNm -RRB- -LCB- infer aspectCode = ` -LSB- package MyPackage ; aspect # -LSB- classNm + `` Aspect '' -RSB- -LCB- before : call -LRB- * #classNm . * -LRB- . . -RRB- -RRB- -LCB- System.out.println -LRB- `` Method called '' -RRB- ; -RCB- -RCB- -RSB- ; System.out.println -LRB- aspectCode.unparse -LRB- -RRB- -RRB- ; -RCB- The generated aspect causes a message to be printed before every call of a method in a class . The name of the affected class is a parameter passed to the MAJ routine . This code also shows the unparse method that MAJ supports for creating a text representation of their code . Our first language extension is simple but a good example to our approach , since it can be defined very quickly and it is hard to implement with alternate means . The Java language ensures that a class can not declare to `` implement '' an interface unless it provides implementations for all of its methods . Nevertheless , this often results in very tedious code . For instance , it is very common in code dealing with the Swing graphics library to implement an event-listener interface with many methods , yet provide empty implementations for most of them because the application does not care about the corresponding events . The example code below is representative : private class SomeListener implements MouseListener , MouseMotionListener -LCB- public void mousePressed -LRB- MouseEvent event -RRB- -LCB- ... / / do something -RCB- public void mouseDragged -LRB- MouseEvent event -RRB- -LCB- ... / / do something -RCB- / / the rest are not needed . Provide empty bodies . public void mouseReleased -LRB- MouseEvent event -RRB- -LCB- -RCB- public void mouseEntered -LRB- MouseEvent event -RRB- -LCB- -RCB- public void mouseExited -LRB- MouseEvent event -RRB- -LCB- -RCB- public void mouseMoved -LRB- MouseEvent event -RRB- -LCB- -RCB- -RCB- Of course , the programmer could avoid providing the empty method bodies on a per-interface basis , by associating each interface with a class that by default provides empty implementations of all interface methods . Then a client class can inherit the empty implementations and only provide implementations for the methods it needs . This pattern is indeed supported in Swing code -LRB- through library classes called adapters -RRB- , but it is usually not possible to employ since the listener class may already have another superclass . Instead , it would be nice to provide a simple Java language extension implemented as an annotation . The implementation of the extension would be responsible for finding the unimple-mented methods and supplying empty implementations by default -LRB- or implementations that just return a default primitive or null value , in the case of methods that have a return 866 type -RRB- . In this case , the above class could be written more simply as : @Implements -LRB- -LCB- `` MouseListener '' , `` MouseMotionListener '' -RCB- -RRB- public class SomeListener -LCB- public void mousePressed -LRB- MouseEvent event -RRB- -LCB- ... / / do something -RCB- public void mouseDragged -LRB- MouseEvent event -RRB- -LCB- ... / / do something -RCB- -RCB- Of course , this extension should be used carefully since it weakens the tests of interface conformance performed by the Java compiler . We implemented the above Java extension using MAJ. The code for the implementation was less than 200 lines long , with most of the complexity in the traversal of Java classes , interfaces , and their methods using reflection . The code processes a set of given Java classes and retrieves the ones with an Implements annotation . It then finds all methods that are in any of the interfaces passed as arguments to the Implements annotation and are not implemented by the current class . For each such method , code is generated in an AspectJ aspect to add an appropriate method implementation to the class . For instance , the code to add the method to the class in the case of a void return type is : infer newMethod = ` -LSB- public void #methodName -LRB- #formals -RRB- -LCB- -RCB- -RSB- ; aspectMembers.add -LRB- newMethod -RRB- ; Finally , the class needs to be declared to implement the interfaces specified by the annotation . This is easily done by emitting the appropriate AspectJ code : infer dec = ` -LSB- declare parents : # -LSB- c.getName -LRB- -RRB- -RSB- implements # -LSB- iface.getName -LRB- -RRB- -RSB- ; -RSB- ; The final aspect -LRB- slightly simplified for formatting reasons -RRB- generated for our earlier listener class example is : public aspect SomeListenerImplementsAspect1 -LCB- void SomeListener.mouseEntered -LRB- MouseEvent e -RRB- -LCB- -RCB- void SomeListener.mouseExited -LRB- MouseEvent e -RRB- -LCB- -RCB- void SomeListener.mouseMoved -LRB- MouseEvent e -RRB- -LCB- -RCB- void SomeListener.mouseReleased -LRB- MouseEvent e -RRB- -LCB- -RCB- declare parents : SomeListener implements MouseListener ; declare parents : SomeListener implements MouseMotionListener ; -RCB- This aspect performs exactly the modifications required to the original class so that it correctly implements the MouseListener and MouseMotionListener interfaces . We invite the reader to consider how else this language extension might be implemented . Our approach of using annotations in combination with MAJ yielded a very simple implementation by letting AspectJ deal with most of the complexities of Java . Specifically , we did not have to deal with the low-level complexities of either Java source syntax or Java bytecode . For instance , we did not have to do any code parsing to find the class body or declaration that needs to be modified . Dealing with Java syntactic sugar , such as inner classes , was automatic . We did not need to do a program transformation to add the implements clauses or the extra methods to the class . Similarly , we did not need to worry about the valid syntax for adding an implemented interface if the class already implements another . Our second example language extension addresses a common programming need , especially in server-side programming . Software applications often find the need for pooling frequently-used objects with high instantiation costs . We use the following database connection class as a running example : public class DBConnection -LCB- public DBConnection -LRB- String dbURI , String userName , String password -RRB- -LCB- ... -RCB- public void open -LRB- -RRB- -LCB- ... -RCB- public void close -LRB- -RRB- -LCB- ... -RCB- -RCB- The cost of an open -LRB- -RRB- call is very high for a database connection . In applications concerned with performance , such as high-volume websites with lots of database requests , one often finds the need to pool database connections and keep them open , instead of repeatedly creating new ones and opening them . Making a class such as DBConnection into a `` pooled '' class involves at the very least creating a pooling manager class that knows how to manage instances of the class being pooled . A different pooling manager class is needed for each class being pooled , since the manager needs to have class-specific information such as how to instantiate a new instance of the class when the pool is running low -LRB- e.g. , DBConnection objects are created by a constructor call , followed by an open -LRB- -RRB- call -RRB- , and how to uniquely identify objects of the same class that belong to different pools -LRB- e.g. , DBConnection objects of different dbURI , userName , and password combinations need to be in different pools , and the pooling manager needs to understand which pool to fetch objects from when a request arrives -RRB- . We expressed the pooling concept as a language feature that can used transparently with any Java class , as long as some broad properties hold regarding its construction and instantiation interface . The rest of the application will be completely oblivious to the change . This facilitates the application of pooling after a large code base which uses the class in its non-pooled form has been developed . Using our extension , converting a class to a pooled class involves only 4 annotations : @pooled , @constructor , @request , and @release . For example , to convert the DBConnection class into a `` pooled '' class , and to adapt an existing code base to using the pooled functionality , the user only has the add the following annotations to the code : @pooled -LRB- mgr = pooled.PoolTypes.BASIC , max = 10 , min = 2 -RRB- public class DBConnection -LCB- @constructor public DBConnection -LRB- String dbURI , String userName , String password -RRB- -LCB- ... -RCB- 867 @request public void open -LRB- -RRB- -LCB- ... -RCB- @release public void close -LRB- -RRB- -LCB- ... -RCB- -RCB- The @pooled annotation indicates that class DBConnection should be pooled . It accepts parameters that can be used to customize the pooling policy . @constructor annotates the constructor call whose parameters serve as unique identifiers for different kinds of DBConnection objects . In this example , DBConnection objects with different dbURI , userName , and password combinations should be maintained separately . @request annotates the method that signals for the request of a pooled object , and @release annotates the method call that signals for the return of the pooled object back to the pooling manager . The implementation of this extension using MAJ is less than 400 lines of code . The MAJ program searches for classes annotated with @pooled , and generates two Java classes and one aspect to facilitate converting this class to be pooled . We next describe the generated code in more detail . The reader may want to consider in parallel how the same task could be accomplished through other means . Neither conventional Java facilities -LRB- i.e. , classes and generics -RRB- nor AspectJ alone would be sufficient for expressing the functionality we describe below in a general way , so that it can be applied with little effort to arbitrary unomdified classes . For instance , none of these facilities can be used to create a proxy class with methods with identical signatures as those of an arbitrary Java class . First , a pooling manager class , PoolMgrForDBConnection , is generated for DBConnection . The pooling manager class contains methods for requesting and releasing pooled DBConnection objects , as well as code to manage the expansion of the pool based on the min and max parameters . In order to retrofit an existing code base to use DBConnection as a pooled class , we need to introduce proxy objects that will be used wherever an object of the original class would exist in the application code . This is necessary as different objects from the perspective of the client code will correspond to the same pooled object . We generate a proxy class as a subclass of the pooled class . In our example : DBConnection_Proxy extends DBConnection . All instances of the proxy class share a static reference to an instance of PoolMgrForDBConnection . Each proxy instance holds -LRB- non-static -RRB- references to the parameters to the @constructor constructor call , and the DBConnection object obtained from the pooling manager . The proxy class rewrites the @request and @release methods : the @request method is rewritten to obtain an object of DBConnection type from the pooling manager , using the unique identifiers kept from the constructor call , and the @release method returns the DBConnection method back to the pool , while setting the reference to this object to null . The MAJ code in the proxy takes care to exactly replicate the signature of the original methods , including modifiers and throws clauses . For instance , the @release method in the proxy is generated as : infer meth = ` -LSB- #mods #ret # -LSB- m.getName -LRB- -RRB- -RSB- -LRB- #formals -RRB- #throwStmt -LCB- m_poolMgr . release -LRB- m_uniqueId , m_proxiedObj -RRB- ; m_proxiedObj = null ; -RCB- -RSB- ; All other methods simply delegate to the same method in the superclass . The idea is to have variables declared to hold a DBConnection object , now hold a DBConnection_Proxy object . Therefore , to complete the `` proxy '' pattern , we need to change all the calls of new DBConnection -LRB- ... -RRB- to new DBConnection_Proxy -LRB- ... -RRB- . This is the role of our generated aspect : tedious recoding effort is easily replaced by an aspect : the aspect intercepts all the constructor calls of DBConnection , and returns an object instantiated by calling new DBConnection_Proxy -LRB- ... -RRB- . In summary , a user can easily turn a class into a pooled class , and retrofit any existing code base to use this class in its new , pooled form . The client code does not need to be hand-edited at all , other than with the introduction of our 4 annotations . We believe that the years to come will see the emergence of a healthy ecology of small language extensions based on the annotation features of Java and C# . There are already major examples of such extensions , especially with distribution - and persistence-related annotations , implemented in the context of J2EE Application Servers . Such extensions can be implemented with heavyweight support-e . g. , parsing files , or recognizing annotations in a class loader and performing bytecode manipulation . In fact , the JBoss AOP mechanism -LRB- in whose early design and implementation we have played an active role -RRB- is the foremost example of infrastructure used to implement annotation-based language extensions . Nevertheless , experience from compilers in general-purpose languages has shown that it is beneficial to develop a mature back-end language and implement high-level features by translating to that back-end . Our approach proposes that AspectJ is well-suited as such a back-end language for small Java language extensions and that generating AspectJ code offers significant simplicity benefits . In the future we plan to support this claim with more examples and perform a thorough comparison with competing mechanisms . -LSB- 1 -RSB- G. Kiczales , E. Hilsdale , J. Hugunin , M. Kersten , J. Palm , and W. G. Griswold . An overview of AspectJ . In ECOOP ' 01 : Proceedings of the 15th European Conference on Object-Oriented Programming , pages 327 353 , London , UK , 2001 . Springer-Verlag . -LSB- 2 -RSB- G. Kiczales , J. Lamping , A. Menhdhekar , C. Maeda , C. Lopes , J.-M . Loingtier , and J. Irwin . Aspect-oriented programming . In M. Ak sit and S. Matsuoka , editors , Proceedings European Conference on Object-Oriented Programming , volume 1241 , pages 220 242 . Springer-Verlag , Berlin , Heidelberg , and New York , 1997 . -LSB- 3 -RSB- Y. Smaragdakis . A personal outlook on generator research . In C. Lengauer , D. Batory , C. Consel , and M. Odersky , editors , Domain-Specific Program Generation . Springer-Verlag , 2004 . LNCS 3016 . -LSB- 4 -RSB- D. Zook , S. S. Huang , and Y. Smaragdakis . Generating AspectJ programs with meta-AspectJ . In Generative Programming and Component Engineering -LRB- GPCE -RRB- , pages 1 18 . Springer-Verlag , October 2004 . 868

O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O B O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O B O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O B O O O O O O B O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B B I O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O B O O O O O O O O B O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O B O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O B O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B B I O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O

simplicity
language extension
java
language extensions
annotation

domain-specific languages
domain-specific language
meta-aspectj