Head blast, PO2VO, vo2do, do2dto, a bunch of object properties, take them out and stuff them in. If it weren’t for the various layers of anti-corrosion under the DDD architecture, I would like to fight against it.

Beanutils.copyproperties: MapStruct generates x.et (Y.et) code at compile time, and the final result is the best. The overall compression data is as follows:

  • BeanUtils.copyPropertiesIs the most common utility class in your code, as long as you don’t use it incorrectlyApachePackage, but using Spring, and there is basically no performance impact.
  • But if the performance is better, you can replace manualThe get and set, orMapStructBetter because it is itself generated at compile timeThe get and setCode, and we writeThe get and setThe same.
  • Some other component packages are primarily based onAOP,ASM,CGlib, the technical means to achieve, so there will be corresponding performance loss.

Do how? Write a MapStruct for every operation that transforms an object property? Also not suitable ah, some methods are very simple operation, write code can be done, the problem is lazy to write, a lot of easy to write wrong. Not to mention beanutils.copyProperties are sometimes identified as having performance problems, with properties being added and subtracted from the code

Therefore, I want to write an IDEA Plugin to solve this problem. The purpose is to define the two objects whose attributes I need to convert through the IDEA plug-in development ability, and automatically generate the conversion codes of the two objects and weave them into my object positioning position.

Designing a plug-in

I think so: in the IDEA development project in the code, the need to convert between two objects, copy the first objects and attributes, and then translate the cursor to the object, then I give it a button or shortcut key, is to transform all code generation to come out, so don’t need to solve the problem of handwritten, results are as follows:

1. Engineering structure

Vo2dto ├ ─ ─. Gradle └ ─ ─ the SRC ├ ─ ─ the main │ └ ─ ─ Java │ └ ─ ─ cn. Bugstack. Guide. Idea. The plugin │ ├ ─ ─ action │ │ └ ─ ─ Vo2DtoGenerateAction. Java │ ├ ─ ─ application │ │ └ ─ ─ IGenerateVo2Dto. Java │ ├ ─ ─ domain │ │ ├ ─ ─ model │ │ │ ├ ─ ─ GenerateContext. Java │ │ │ ├ ─ ─ GetObjConfigDO. Java │ │ │ └ ─ ─ SetObjConfigDO. Java │ │ └ ─ ─ service │ │ ├ ─ ─ impl │ │ │ └ ─ ─ GenerateVo2DtoImpl. Java │ │ └ ─ ─ AbstractGenerateVo2Dto. Java │ └ ─ ─ proceeds │ └ ─ ─ Utils. Java ├ ─ ─ resources │ └ ─ ─ Meta-inf │ ├─ build.org.txt ├─ build.org.txt ├─ build.org.txtCopy the code

Source code: github.com/fuzhengwei/… – Welcome to submit issue and PR for joint maintenance

This IDEA plug-in project is mainly divided into four areas:

  • Action: provides the menu bar form that we configured in the plugin toGenerateThis is where you normally generate get, set, and constructor methods.
  • Application: The application layer defines the interface, which defines a method interface for generating code and weaving it into anchors.
  • Domian: The domain layer deals exclusively with code generation and weaving. This layer takes care of the anchor location fetching, clipboard information copying, application context, class get, set parsing, and finally weaving the generated code into the anchor.
  • Infrastructure: Provides utility classes at the base layer for operations such as obtaining clipboard information and determining anchor position.

2. Weave into the code interface

cn.bugstack.guide.idea.plugin.application.IGenerateVo2Dto

public interface IGenerateVo2Dto {

    void doGenerate(Project project, DataContext dataContext);

}
Copy the code
  • Defining the interface is a very important step, because this step defines the generation standard, from which all the generation action will be initiated.Learning source code is the same, you have to find a core entry point, in order to better start learning

3. Define template methods

Because the operation of generating code and weaving in the anchor position is actually a set of flow operations as a whole, because in this process you need; Get the context information (that is, the project object), extract the set method set for the class of the current anchor position, and then extract the GET method set by reading the information on the Ctrl+C clipboard. The fourth step is to combine the set and GET and weave the code into the anchor position. The overall process is as follows:

  • Using the template approach, it is very easy to split the pieces of code written in a class according to their responsibilities.
  • And because you have a template definition, you have a standard set of processes defined, and it’s easier to execute code under process specifications and then add logical iteration capabilities.

4. Code is woven into anchor points

Before the code is woven into the anchor point, the methods defined in the template class need to be handled by the implementation interface, mainly including:

  1. throughCommonDataKeys.EDITOR.getData(dataContext),CommonDataKeys.PSI_ELEMENT.getData(dataContext)Encapsulate GenerateContext object context information, that is, some class, anchor position, document edit object.
  2. Use PsiClass to obtain the Class information corresponding to the cursor positionpsiClass.getMethods()Read object method, filter out the set method, encapsulate into the collection.
  3. throughToolkit.getDefaultToolkit().getSystemClipboard()Get the clipboard information that you generated for the object at the anchor pointx.set(y.get)When, copy the Y Y object and start extracting the GET method, also encapsulated into the collection.
  4. So finally, the code assembly and weaving action, this part of our code is as follows;

cn.bugstack.guide.idea.plugin.domain.service.impl.GenerateVo2DtoImpl

@Override
protected void weavingSetGetCode(GenerateContext generateContext, SetObjConfigDO setObjConfigDO, GetObjConfigDO getObjConfigDO) {
    Application application = ApplicationManager.getApplication();
    // Get the length of the space position
    int distance = Utils.getWordStartOffset(generateContext.getEditorText(), generateContext.getOffset()) - generateContext.getStartOffset();
    application.runWriteAction(() -> {
        StringBuilder blankSpace = new StringBuilder();
        for (int i = 0; i < distance; i++) {
            blankSpace.append("");
        }
        int lineNumberCurrent = generateContext.getDocument().getLineNumber(generateContext.getOffset()) + 1;
        List<String> setMtdList = setObjConfigDO.getParamList();
        for (String param : setMtdList) {
            int lineStartOffset = generateContext.getDocument().getLineStartOffset(lineNumberCurrent++);
            
            WriteCommandAction.runWriteCommandAction(generateContext.getProject(), () -> {
                generateContext.getDocument().insertString(lineStartOffset, blankSpace + setObjConfigDO.getClazzParamName() + "." + setObjConfigDO.getParamMtdMap().get(param) + "(" + (null == getObjConfigDO.getParamMtdMap().get(param) ? "" : getObjConfigDO.getClazzParam() + "." + getObjConfigDO.getParamMtdMap().get(param) + "()") + "); \n");
                generateContext.getEditor().getCaretModel().moveToOffset(lineStartOffset + 2); generateContext.getEditor().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); }); }}); }Copy the code
  • Weave into the code process action, mainly on the set method set traversal, the correspondingx.set(y.get)throughdocument.insertStringTo the specific location and code.
  • Finally, all of the generated code methods are woven into completion, that is, completex.set(y.get)In the process.

5. Configure the menu entry

plugin.xml

<actions> <! -- Add your actions here --> <action id="Vo2DtoGenerateAction" class="cn.bugstack.guide.idea.plugin.action.Vo2DtoGenerateAction"
            text="Vo2Dto - Little Fuge." description="Vo2Dto generate util" icon="/icons/logo.png">
        <add-to-group group-id="GenerateGroup" anchor="last"/>
        <keyboard-shortcut keymap="$default" first-keystroke="ctrl shift K"/>
    </action>
</actions>
Copy the code
  • So this time we’re going to generatex.set(y.get)Add a shortcut key to the operation of the code, so that we can operate more conveniently.

Installation and use verification

  • Since plugins need to go to plugins.jetbrains.com/ and wait for approval, they can be downloaded from the release package: github.com/fuzhengwei/… Download and install manually.

Then you can convert the object So Easy, as follows:

  1. Copy the object that you need to convert, because then the plug-in can get the clipboard information and extract the set of GET methods.
  2. Define the mouse over the object to which you want to convert the Settings, right click, and selectGenerate -> Vo2Dto - Little Fuge

1. Copy objects

2. Generate objects

3. End result

  • Eventually you’ll see how nice it is to have all your objects converted and automatically generated code.
  • If you just use the shortcut keysCtrl + Shift + KIt can also be generated automatically.

Take it and use it. You’d better make some suggestions, submit an issue, submit PR, all are very welcome!