[RSS]
When generating code, the existing source code must not be overridden. We should instead merge the generated source code into the existing source code. There are going to be two types of code in a source file. The first is the source that is generated via the template code generation. The second is the source code that is written by the user. There will also be times when the user may want to override the code that is generated by the templates. To give the user the ability to override the code that is generated for a section of the source code, some sort of annotation will be used. The annotation may not be a Java Annotation, since Java annotations requires a Annotation declaration in order to compile the source code. Since users may not want there Java project to contain this extra declaration, it may be best to use Javadoc tags.
public class MyClass
{
    /**
     * @generated
     */
   public void foo()
   {
      <Some Method Details>
   }
}

In the above example demostrates a Java method that is generated by the code generation mechanism. The source code synchronization process will replace the entire method 'foo, when synchronizing the source code. To override the implementation of 'foo', the @generated tag must removed. The source code synchronization process will no longer replace the 'foo' method during code generation.

Must Have Features

  • Synchronized generated source code with exising source files (99444)
  • Allow users to override the code generation for a method, and attribute (99447)

Implementation of source code merging in Netbeans 6.0 UML.

1. Domain Templates configuration API produces set of templates applicable to the element that code generation is being requested for.

2. Taken together - target directory, the element and applicable templates - produce set of target file paths where the generation will happen into. If any of the files already exist, then it is considered as a candidate for a merge with corresponding new file. 2.1.Base condition - it should be a correctly parseable Java file. If not, then back-up copy will be made and new file will replace the old one, and warning will be logged.

3. If target files don't exist when the "Source File Artifact" property of the element is checked for pointing to a potential merging candidate. 3.1.Again, to be considered it should be a correctly parseable Java file. 3.2.Second condition - only marked with ID (as defined in 7.2.3) class(es) inside it, or if there is a public class declared inside it, then only the public one and only if marked with ID, will be considered. 3.3.Each new file that doesn't have pre-existing version as defined in 2. will be parsed and ID(s) of its marked class(es), or if there is a public class declared inside it, then only the ID, if any, of the public one will be used for search among ID(s) defined in 3.2. If a match found that the file where the matching ID is defined will be considered as pre-existing version to be merged with the new file.

4.For each pair - new file and its pre-existing version as defined in 2.x or 3.x - the search for matching elements is performed. 4.1. Elements (types, attributes, methods, enum literals) of new file are matched against elements of the same type from the pre-existing version. 4.1.1.First attempt to match is done using marker IDs (defined in 7.2.3). 4.1.2.Rest of non-matched elements is matched using names (for types, enum literals and attributes) and signatures for operations.

5.1. An element is considered "regeneratable" if it has a marker specifying so (defined in 7.2.1). 5.2. An regeneratable operation, type (and enum literal TBD) element is by default only header-regeneratable (see 7.2.2), ie. when element is updated with new version only the header of the element (see 5.3.x) would be updated leaving the body of the declaration unmodified. 5.2.1. Using marker the element can be explicitly specified to be header+body regeneratable (see 7.2.2). 5.3. For purposes of source code modifications an element is a type, attribute, operation or enum literal declaration preceded, if any, by single line comments (including marker ones) preceded, if any, by javadoc comments. 5.3.1. The "header" of an element is the header of the element declaration plus the comments as described in 5.3.

6. For each pair - new file and its pre-existing version as defined in 2.x or 3.x - the modification of pre-existing version if performed based on the results of the match in 4.x and marker instructions described in 5.x 6.1. Each "regenerateable" "old" element for which matching "new" element was found is replaced with the new element (a header only or header+body of the declaration is replaced as described in 5.2) 6.2. Each "regeneratable" "old" element for which a matching "new" element was not found is deleted from the pre-existing source. 6.3. Each new element for which a matching old element was not found is added to the pre-existing source.

7. Markers 7.1 immediately preceding an element a single line comment (that possibly enclosed in Netbeans Java Editor code-folding comments) of the form : // #[(name=value(,name=value)*)?] 7.2. Recognized parameters 7.2.1. "regen=yes/no", default if the parameter isn't present - "no". Specifies whether the element is "regeneratable" (5.1) 7.2.2. "regenBody=yes/no", default if the parameter isn't present - "no". Specifies whether the element is header-regeneratable or header+body regeneratable (5.2) 7.2.3. "id=<an unique id value>", no default. An id to be used for matching (4.1.1)

Samples.

1. Markers generated by default /** * cl2 comment */ // #[regen=yes,id=DCE.837531C6-88E2-92F9-401E-EC3D10886772] public class cl2 { // #[regen=yes,id=DCE.D113E820-6111-0ACD-3734-107284B942AC] private String Attr1; // #[regen=yes,id=DCE.A68261A9-6DCE-418D-3E81-7863E83C205B] public void op1 () { } // #[regen=yes,regenBody=yes,id=DCE.02E281C8-C473-EB3F-08A2-6967B09A4ACD] public String getAttr1 () { return Attr1; } // #[regen=yes,regenBody=yes,id=DCE.4D5F8CF3-9820-B029-5095-F03AA41EE94E] public void setAttr1 (String val) { this.Attr1 = val; } /** * clas2 comment */ // #[regen=yes,id=DCE.53C71074-4D93-0C5F-82E1-ABE5DE2C30F1] class clas2 { } }

2. Let suppose there is an existing source code that was RE-ed into UML model and we'd like for the (some parts of) code to be regenerated from the model. To accomplish that we'd need manually add marker(s) as it shown below for attribute Attr1. /** * cl2 comment */ public class cl2 { /** * Attr1 comment */ // #[regen=yes] private String Attr1; /** * Attr2 comment */ private String Attr2; /** * clas2 comment */ class clas2 { } } Next time code is generated from the model the Attr1 will be matched by name (acc. to 4.1.2) and updated with new version (acc. to 6.1). /** * cl2 comment */ public class cl2 { /** * Attr1 comment modified in UML documentation property editor */ // #[regen=yes,id=DCE.6914EA88-3C15-40EE-7B14-2D28B9CA4FF3] private String Attr1; /** * Attr2 comment */ private String Attr2; /** * clas2 comment */ class clas2 { } } Once it got ID-marked the attribute can even be renamed in the model and still matched using its ID during next code generation/merging, and thus renamed in the source code as well. /** * cl2 comment */ public class cl2 { /** * Attr1 comment modified in UML documentation property editor */ // #[regen=yes,id=DCE.6914EA88-3C15-40EE-7B14-2D28B9CA4FF3] private String[] Former_Attr1; /** * Attr2 comment */ private String Attr2; /** * clas2 comment */ class clas2 { } }