Modeling using Eclipse Modeling Framework, Part 3

xiaoxiao2021-03-06  77

Use Eclipse JMERGE custom-generated code and editor

Level: Intermediate

Adrian Powell

Senior software developers, IBM 2004 June

Eclipse Modeling Framework (EMF) contains an open source tool JMERGE that allows code to generate more flexible and can be better. This article uses an example to show how to add JMERGE to an application and customize JMERGE behavior for different environments.

Overview The previous article of this series describes the knowledge about Eclipse's Java Emitter Templates (Jet) and code generation. In that article, you have seen how to save time by using template and code generator, and implement mode Level code reuse. However, in most cases, this is not enough. You need to insert the generated code into the existing code, or allow future developers to customize the generated code without having to rewrite any content when regenerating code. Ideally, the coded generator's creator wants to support all future needs: from the implementation of the modification method, modify various method signs to modify the inheritance structure of the generated class. This is a very interesting question, there is no very good universal solution; but there is a good pure Java solution called Jmergen.

JMERGE is a tool for an open source included in the EMF, allowing you to customize the generated model and editor, and the re-generated code will not damage the modified content. If you describe how to combine newly generated code into existing cord, Jetemitter can support JMERGE. This article shows some of the available options in one example.

The first step is assumed that you have added a new project, you need to create a JUnit test class for each class you need to write, so you must test each method written. As a serious and efficient (or relatively lazy) programmer, you decided to write a plugin, it accepts a Java class as an input and generates the settle of the JUnit test example (STUB). You have created JET and plugins, now you want to allow users to customize the generated test class; however, when the original class interface changes, it is still necessary to regenerate code. To implement this feature, you can use JMERGE.

Call JMERGE from the plugin is very simple (see Listing 1). This creates a new JMERGER instance, as well as a URI Merge.xml, setting the source and target to merge, and call merger.merge (). Then the merged content can be expanded to Merger.getTargetCompiLationUnit ().

Listing 1. Call JMERGE

// ...

JMERGER Merger = getjmerger ();

// set Source

Merger.SetSourceCompiLationUnit

Merger.createCompilationUnitForContents (generated);

// set Target

Merger.SetTargetCompiLationUnit (

Merger.createCompiLationUnitForinputStream

NEW fileInputStream (TARGET.GETLOCATION (). Tofile ()))));

// Merge Source and Target

Merger.mege ();

// extract merge contents

InputStream MergedContents = New ByteArrayInputStream (Merger.getTargetCompiLationUnit (). GetContents (). GetBytes ());

// Overwrite the target with the merge contents

Target.SetContents (MergedContents, True, False, Monitor);

// ...

// ...

Private JMerger getjmerger () {

// Build Uri for Merge Document

String Uri =

Platform.getPlugin (Plugin_ID) .GetDescriptor (). GetInstallURL (). Tostring ();

URI = "Templates / Merge.xml";

JMERGER JMERGER = New JMERGER ();

JControlModel ControlModel = New JCONTROLMODEL (URI);

JMerger.SetControlModel (ControlModel);

Return JMERGER;

}

To launch this process, you can use this simple merge.xml. Among them, the tag, as well as the default namespace declaration. The main part of this code is in the Merge: Pull element. Here, the code of each method in the source class is replaced with the code of the corresponding method of the target class. If a method does not exist in the target class, it will be created. If a method exists only in the source class, it will be retained in the target class.

Listing 2. A very simple merge.xml

"http://www.eclipse.org/org/eclipse/emf/codegen/jmerge/options>

Sourceget = "Method / GetBody"

TargetPut = "Method / setBody" />

Distinguish this simple method has a very obvious question: Each time you modify the source class and regenerate the code, the previous modification is all lost. We need to add a mechanism to tell Jmerge how some methods have been modified, so these methods should not be rewritten. To implement this feature, you can use the element. MERGE: DictionaryPattern allows you to distinguish between Java elements with regular expressions (see Listing 3).

Listing 3. A simple DictionaryPattern

Name = "generatedMember"

SELECT = "Member / getcomment"

Match = "/ s * @ / s * (gen) rating / s * / n" />

TargetMarkup = "^ gen $"

Sourceget = "Method / GetBody"

TargetPut = "Method / setBody" />

DictionaryPattern defines a regular expression that matches a member containing "@generated" in the comment. The SELECT property lists which parts to which they want to compare the regular expressions given in the Match property. DictionaryPattern is defined by a string GEN, which is the content in the parentheses in the match property. MERGE: PULL element is more than an additional property targetmarkup. This property can match DictionaryPattern, which must match the target code before applying the merge rules. Here, we are checking the target code, not the source code, so the user can customize these code. When the user deletes the "@generated" tag in the comment, DictionaryPattern does not match the target code, so this method body will not be merged. See Listing 4.

Listing 4. Custom code

/ **

* Test Case for getname

* @generated

* /

Public void testsimplegetname () {

// Because of the @generated tag,

// any code in this Method Will Be Overridden

}

/ **

* Test Case for getname

* /

Public void testsimplesetname () {

// Code in this method Will Not Be Regenerated

}

You may notice that some elements cannot be customized, any attempt to customize these code should be stopped. To support this feature, you want to define another DictionaryPattern, which is responsible for finding other tags in the source code (not the target code), such as @unmodifiable. Then define a PULL rule to check SourceMarkup, not TargetMarkup, which prevents the user from deleting tags or hinders merge operations. See Listing 5.

Listing 5. Merge.xml that cannot be modified

Name = "generatedUnmodifiablemembers"

SELECT = "Member / getcomment"

Match = "/ s * @ / s * (unmod) ifiable / s * / n" />

SourceMarkup = "^ unmod $"

Sourceget = "Member / getBody"

TargetPut = "MEMBER / SETBODY" />

Fine-grained customization After using this solution For a while, you will notice some methods with some universal unmodible code (such as tracking and logging code) in customized code (such as tracking and logging code). At this time we don't want to prohibit generating code, and you don't want all the code to generate the entire method, but hope to allow users to customize some of the code.

To implement this feature, you can replace the list 6 in front of the PULL target.

Listing 6. Custom code for fine particles

t The Source is the standard ->

TargetMarkup = "^ gen $"

Sourceget = "Method / getBody" SourceTransfer = "(/ s * /// s * begin-user-code. *? /// s * end-user-code / s *) / n"

TargetPut = "Method / setBody" />

This will only rewrite the contents of the string "// begin-user-code" and "// end user-code", so the content between the two can be retained in the custom code. In the regular expression above, "?" Indicates that in addition to the content to be replaced, other content is reserved in addition to the content to be replaced. You can realize a similar feature with Javadoc comments, so you can copy your comments, while customizing the space for users. See Listing 7.

Listing 7. Customized Javadoc customization

And end-user-doc tags ->

SourceMarkup = "^ gen $"

Sourceget = "member / getcomment"

SourceTransfer = "(/ s * / s *) / n"

TargetMarkup = "^ gen $"

TargetPut = "MEMBER / setcomment" />

To support this comment, first modify the start tag and end tag to follow the HTML annotation syntax so that they do not appear in the generated javadoc; then modify the Sourceget and TargetPut properties to use "Member / Getcomment" and "MEMBER / SETCOMMENT". JMERGE allows you to access different parts of Java code at fine granular levels. (For more details, please refer to Appendix A).

Next, we have introduced how to convert the method, but Jmerge can handle domain, initialization, exception, return value, import statement, and other Java elements. They also use similar basic ideas, and may only be modified. Reference plugins / org.eclipse.emf.codegen_1.1.0 / test / merge.xml you can know how to use these features (I use Eclipse 2.1, so if you use other versions of Eclipse, then the version of the ECore plugin may Will be different). This example is very simple, there is no SourceTransfer tag, but this example shows how to handle exceptions, flags, and other Java elements.

More complex examples, please see the method of using the JMERGE: plugins / org.eclipse.emf.codegen.ecore_1.1.0 / templates / emf-merge.xml. From this example, it can be seen that EMF only allows part to customize Javadoc, but use some of the techniques described above, you can add support to the methodology (this can enhance the functions of Jet).

Appendix A: Effective Target Options In DictionaryPattern and Pull rules, we have used "Member / getcomment" and "Member / GetBody" and their setter methods, but there are many other options. Jmergen supports any classes defined in org.eclipse.jdt.core.jdom.IDOM *. All available options are shown in Table 1. Table 1. Effective target options

Method Comment Type CompilationUnitgetHeader / setHeadergetName / setNameFieldgetInitializer / setInitializer does not contain "=" getName / setName variable name getName / setName class name ImportgetName / setName either a fully qualified type name, either an on-demand package InitializergetName / setNamegetBody / setBodyMembergetComment / setcommentGetflags / setFlags, for example: Abstract, Final, Native, etc. MethodaddExceptionaddParametergetBody / setBodygetName / setNamegetParameterNames / setParameterNamesgetParameterTypes / setParameterTypesgetReturnType / setReturnTypePackagegetName / setNameTypeaddSuperInterfacegetName / setNamegetSuperclass / setSuperclassgetSuperInterfaces / setSuperInterfaces

Appendix B: MERGE: PULL Attributes Table 2 gives the attribute of the Merge: PULL element.

Table 2. MERGE: PULL attribute

Attribute conditions Sourceget must be required. This value must be an option listed in Appendix A, such as "MEMBER / GETBODY". TargetPut is required. This value must be an option listed in Appendix A, such as "Member / SetBody". SourceMarkup is optional. Filtering the DictionaryPatterns that must match the source code before triggering the Merge: PULL rule. Formats such as "^ DictionaryName $", you can also use "|" to merge multiple DictionaryPatterns in a row. TargetMarkup is optional. Filtering the DictionaryPatterns that must match the target code before filtering the Merge: PULL rules. Formats such as "^ DictionaryName $", you can also use "|" to merge multiple DictionaryPatterns in a row. SourceTransfer is optional. A regular expression that specifies the number of source code to be passed to the target code.

Reference

Other articles on the Eclipse Modeling Framework series on developerWorks: Part 1 creates and uses the EMF model, and Part 2 uses Java Emitter Templates (Jet) to generate code. Download the JUnit plugin source code used herein. Download the final merge.xml file used in this article. All documents, source code, and latest compiler are available on the EMF project home page. IBM Red Books Eclipse Development Using The Graphical Edition Framework and The Eclipse Modeling Framework has more detailed examples, which describes more customization features. If you have any questions, you can access the EMF newsgroup. If you have not used the Eclipse newsgroup, read the rules and how to apply for a password. There is more articles provided for Eclipse users in the open source project area of ​​DeveloperWorks. See the latest Eclipse technology download area in AlphaWorks. On the Open Source Area of ​​Developer Bookstore, hundreds of books on open source topics can be found, including several books on Eclipse. Subscribe to developerWorks, use the latest IBM tools and middleware introduced and test applications: You can get the IBM's various software, from Eclipse-based WebSphere, DB2, Lotus, Rational, and Tivoli, as a period of 12 software The license of a month, these content can only be obtained very much. Subscribe developerWorks, download a free trial version that runs on Linux product from Speed-start your Linux app section of developerWorks, including WebSphere Studio Site Developer, WebSphere SDK for Web services, WebSphere Application Server, DB2 Universal Database Personal Developers Edition, Tivoli Access Manager and Lotus Domino Server. This will be gate faster and helps to collect documents and technical support for each product. About the author Adrian Powell starts using the IBM's Java development tool from just starting to join the Visualage for Java Enterprise Tooling team, here he spends two years to manually write a code generator. Since then, he has been engaged in the development of tools and plugins in Eclipse and Visualage for Java. He now develops such tools and plugins almost every version of Eclipse and Visualage for Java. Adrian currently engaged in the research of e-commerce innovation in IBM, here he read source code and provided some support for colleagues.

转载请注明原文地址:https://www.9cbs.com/read-94081.html

New Post(0)