[
  {
    "path": ".idea/$CACHE_FILE$",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectInspectionProfilesVisibleTreeState\">\n    <entry key=\"Project Default\">\n      <profile-state>\n        <expanded-state>\n          <State />\n          <State>\n            <id>Ali-Check</id>\n          </State>\n        </expanded-state>\n        <selected-state>\n          <State>\n            <id>AlibabaBooleanPropertyShouldNotStartWithIs</id>\n          </State>\n        </selected-state>\n      </profile-state>\n    </entry>\n  </component>\n</project>"
  },
  {
    "path": ".idea/.gitignore",
    "content": "# Default ignored files\n/workspace.xml\n# Project exclude paths\n/.\n/../../\n\n\n\n\n# Datasource local storage ignored files\n/dataSources/\n/dataSources.local.xml\n"
  },
  {
    "path": ".idea/D8gerAutoCodePluginProjectSetting.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"com.xyz.caofancpu.d8ger.setting.D8gerProjectState\">\n    <option name=\"voCheck\" value=\"true\" />\n    <option name=\"handlerCheck\" value=\"true\" />\n    <option name=\"controllerCheck\" value=\"true\" />\n    <option name=\"moPath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/mo\" />\n    <option name=\"mapperPath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/mapper\" />\n    <option name=\"mapperExamplePath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/mapper/example\" />\n    <option name=\"mapperXmlPath\" value=\"$PROJECT_DIR$/src/main/resources/mybatis\" />\n    <option name=\"sqlPath\" value=\"$PROJECT_DIR$/doc\" />\n    <option name=\"voPath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/vo\" />\n    <option name=\"handlerPath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/handler\" />\n    <option name=\"controllerPath\" value=\"$PROJECT_DIR$/src/main/java/com/xyz/caofancpu/d8ger/test/controller\" />\n    <option name=\"defaultUrlPrefix\" value=\"/d8gerAutoCode\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <option name=\"LINE_SEPARATOR\" value=\"&#10;\" />\n    <option name=\"RIGHT_MARGIN\" value=\"500\" />\n    <JavaCodeStyleSettings>\n      <option name=\"CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"99\" />\n      <option name=\"NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"99\" />\n      <option name=\"JD_KEEP_INVALID_TAGS\" value=\"false\" />\n    </JavaCodeStyleSettings>\n    <JetCodeStyleSettings>\n      <option name=\"PACKAGES_TO_USE_STAR_IMPORTS\">\n        <value>\n          <package name=\"java.util\" alias=\"false\" withSubpackages=\"false\" />\n          <package name=\"kotlinx.android.synthetic\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"io.ktor\" alias=\"false\" withSubpackages=\"true\" />\n        </value>\n      </option>\n      <option name=\"PACKAGES_IMPORT_LAYOUT\">\n        <value>\n          <package name=\"\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"java\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"javax\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"kotlin\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"\" alias=\"true\" withSubpackages=\"true\" />\n        </value>\n      </option>\n    </JetCodeStyleSettings>\n    <ScalaCodeStyleSettings>\n      <option name=\"MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE\" value=\"true\" />\n    </ScalaCodeStyleSettings>\n    <codeStyleSettings language=\"JAVA\">\n      <option name=\"RIGHT_MARGIN\" value=\"500\" />\n      <option name=\"CALL_PARAMETERS_WRAP\" value=\"1\" />\n      <option name=\"METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"EXTENDS_LIST_WRAP\" value=\"1\" />\n      <option name=\"THROWS_KEYWORD_WRAP\" value=\"2\" />\n      <option name=\"KEEP_SIMPLE_METHODS_IN_ONE_LINE\" value=\"true\" />\n    </codeStyleSettings>\n    <codeStyleSettings language=\"JSON\">\n      <indentOptions>\n        <option name=\"INDENT_SIZE\" value=\"4\" />\n      </indentOptions>\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"PREFERRED_PROJECT_CODE_STYLE\" value=\"Default\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <annotationProcessing>\n      <profile default=\"true\" name=\"Default\" enabled=\"true\" />\n      <profile name=\"Gradle Imported\" enabled=\"true\">\n        <outputRelativeToContentRoot value=\"true\" />\n        <processorPath useClasspath=\"false\">\n          <entry name=\"$PROJECT_DIR$/../../GRADLE-Repository/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.10/625fc0055674dff70dbc76efa36d0f2c89b04a24/lombok-1.18.10.jar\" />\n        </processorPath>\n        <module name=\"D8gerAutoCode.main\" />\n      </profile>\n    </annotationProcessing>\n    <bytecodeTargetLevel target=\"1.8\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/dataSources.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"DataSourceManagerImpl\" format=\"xml\" multifile-model=\"true\">\n    <data-source source=\"LOCAL\" name=\"d8ger@localhost\" uuid=\"62108bf2-5589-45f1-a1bc-31c51250e2d6\">\n      <driver-ref>mysql.8</driver-ref>\n      <synchronize>true</synchronize>\n      <remarks>local</remarks>\n      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>\n      <jdbc-url>jdbc:mysql://localhost:3306</jdbc-url>\n    </data-source>\n  </component>\n</project>"
  },
  {
    "path": ".idea/dictionaries/D8GER.xml",
    "content": "<component name=\"ProjectDictionaryState\">\n  <dictionary name=\"D8GER\">\n    <words>\n      <w>xtools</w>\n    </words>\n  </dictionary>\n</component>"
  },
  {
    "path": ".idea/dictionaries/ht_caofan.xml",
    "content": "<component name=\"ProjectDictionaryState\">\n  <dictionary name=\"ht-caofan\">\n    <words>\n      <w>caofan</w>\n      <w>caofancpu</w>\n      <w>dibage</w>\n      <w>ocket</w>\n      <w>penta</w>\n      <w>uncapitalize</w>\n      <w>uncapitallize</w>\n    </words>\n  </dictionary>\n</component>"
  },
  {
    "path": ".idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" native2AsciiForPropertiesFiles=\"true\" defaultCharsetForPropertiesFiles=\"UTF-8\">\n    <file url=\"PROJECT\" charset=\"UTF-8\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleMigrationSettings\" migrationVersion=\"1\" />\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"delegatedBuild\" value=\"true\" />\n        <option name=\"testRunner\" value=\"GRADLE\" />\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"gradleHome\" value=\"/usr/local/Cellar/gradle/6.0.1/libexec\" />\n        <option name=\"gradleJvm\" value=\"1.8\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n          </set>\n        </option>\n        <option name=\"useQualifiedModuleNames\" value=\"true\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "content": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project Default\" />\n    <inspection_tool class=\"AbstractBeanReferencesInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"ContextComponentScanInconsistencyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"DuplicatedCode\" enabled=\"true\" level=\"WEAK WARNING\" enabled_by_default=\"true\">\n      <Languages>\n        <language minSize=\"270\" name=\"Java\" />\n      </Languages>\n    </inspection_tool>\n    <inspection_tool class=\"Duplicates\" enabled=\"false\" level=\"WEAK WARNING\" enabled_by_default=\"false\" />\n    <inspection_tool class=\"FlowRequiredBeanTypeInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"InjectionValueTypeInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"JdkProxiedBeanTypeInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"KotlinSpringComponentScan\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"RequiredBeanTypeInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringAopErrorsInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBatchModel\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBeanAutowiringInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBeanConstructorArgInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBeanDepedencyCheckInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBeanInstantiationInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBeanLookupMethodInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringBootAdditionalConfig\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringCacheableComponentsInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringComponentScan\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringContextConfigurationInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringFacetProgrammaticInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringFactoryMethodInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringHandlersSchemasHighlighting\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringIncorrectResourceTypeInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringInjectionValueConsistencyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringIntegrationModel\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringJavaAutowiringInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringJavaConfigInconsistencyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringKotlinAutowiring\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringMVCInitBinder\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringMessageDispatcherWebXmlInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringModelInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringOsgiElementsInconsistencyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringOsgiListenerInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringOsgiServiceCommonInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringRequiredAnnotationInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringRequiredPropertyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringScopesInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringSecurityAnnotationBeanPointersResolveInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringSecurityModelInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringTransactionalComponentInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringWebServicesConfigurationsInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"SpringWebSocketConfigurationInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"UtilSchemaInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"WebflowConfigModelInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"WebflowModelInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n    <inspection_tool class=\"WebflowSetupInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  </profile>\n</component>"
  },
  {
    "path": ".idea/jarRepositories.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RemoteRepositoriesConfiguration\">\n    <remote-repository>\n      <option name=\"id\" value=\"central\" />\n      <option name=\"name\" value=\"Maven Central repository\" />\n      <option name=\"url\" value=\"https://repo1.maven.org/maven2\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"jboss.community\" />\n      <option name=\"name\" value=\"JBoss Community repository\" />\n      <option name=\"url\" value=\"https://repository.jboss.org/nexus/content/repositories/public/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"MavenRepo\" />\n      <option name=\"name\" value=\"MavenRepo\" />\n      <option name=\"url\" value=\"https://repo.maven.apache.org/maven2/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven2\" />\n      <option name=\"name\" value=\"maven2\" />\n      <option name=\"url\" value=\"https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven\" />\n      <option name=\"name\" value=\"maven\" />\n      <option name=\"url\" value=\"http://dl.bintray.com/jetbrains/intellij-plugin-service\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven4\" />\n      <option name=\"name\" value=\"maven4\" />\n      <option name=\"url\" value=\"https://repo.rdc.aliyun.com/repository/130650-snapshot-xdHOzb/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven2\" />\n      <option name=\"name\" value=\"maven2\" />\n      <option name=\"url\" value=\"https://maven.aliyun.com/repository/public\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven3\" />\n      <option name=\"name\" value=\"maven3\" />\n      <option name=\"url\" value=\"https://repo.rdc.aliyun.com/repository/130650-release-LLgOVG/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven2\" />\n      <option name=\"name\" value=\"maven2\" />\n      <option name=\"url\" value=\"https://repo1.maven.org/maven2/\" />\n    </remote-repository>\n  </component>\n</project>"
  },
  {
    "path": ".idea/libraries-with-intellij-classes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"libraries-with-intellij-classes\">\n    <option name=\"intellijApiContainingLibraries\">\n      <list>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIU\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.idea\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIU\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIC\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.idea\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIC\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPY\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.pycharm\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPY\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPC\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.pycharm\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPC\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"clion\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.clion\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"clion\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"riderRD\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.rider\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"riderRD\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"goland\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.goland\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"goland\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n      </list>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ASMPluginConfiguration\">\n    <asm skipDebug=\"false\" skipFrames=\"false\" skipCode=\"false\" expandFrames=\"false\" />\n    <groovy codeStyle=\"LEGACY\" />\n  </component>\n  <component name=\"ExternalStorageConfigurationManager\" enabled=\"true\" />\n  <component name=\"FrameworkDetectionExcludesConfiguration\">\n    <file type=\"web\" url=\"file://$PROJECT_DIR$\" />\n  </component>\n  <component name=\"JavaScriptSettings\">\n    <option name=\"languageLevel\" value=\"ES6\" />\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" default=\"true\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\" />\n</project>"
  },
  {
    "path": ".idea/setting.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"arthas.idea.plugin\">\n    <option name=\"redisAddress\" value=\"\" />\n    <option name=\"redisAuth\" value=\"\" />\n    <option name=\"redisCacheKey\" value=\"\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/uiDesigner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Palette2\">\n    <group name=\"Swing\">\n      <item class=\"com.intellij.uiDesigner.HSpacer\" tooltip-text=\"Horizontal Spacer\" icon=\"/com/intellij/uiDesigner/icons/hspacer.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"1\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"com.intellij.uiDesigner.VSpacer\" tooltip-text=\"Vertical Spacer\" icon=\"/com/intellij/uiDesigner/icons/vspacer.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" />\n      </item>\n      <item class=\"javax.swing.JPanel\" icon=\"/com/intellij/uiDesigner/icons/panel.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JScrollPane\" icon=\"/com/intellij/uiDesigner/icons/scrollPane.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"7\" hsize-policy=\"7\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JButton\" icon=\"/com/intellij/uiDesigner/icons/button.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"0\" fill=\"1\" />\n        <initial-values>\n          <property name=\"text\" value=\"Button\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JRadioButton\" icon=\"/com/intellij/uiDesigner/icons/radioButton.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"RadioButton\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JCheckBox\" icon=\"/com/intellij/uiDesigner/icons/checkBox.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"CheckBox\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JLabel\" icon=\"/com/intellij/uiDesigner/icons/label.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"Label\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JTextField\" icon=\"/com/intellij/uiDesigner/icons/textField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JPasswordField\" icon=\"/com/intellij/uiDesigner/icons/passwordField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JFormattedTextField\" icon=\"/com/intellij/uiDesigner/icons/formattedTextField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTextArea\" icon=\"/com/intellij/uiDesigner/icons/textArea.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTextPane\" icon=\"/com/intellij/uiDesigner/icons/textPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JEditorPane\" icon=\"/com/intellij/uiDesigner/icons/editorPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JComboBox\" icon=\"/com/intellij/uiDesigner/icons/comboBox.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"2\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JTable\" icon=\"/com/intellij/uiDesigner/icons/table.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JList\" icon=\"/com/intellij/uiDesigner/icons/list.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"2\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTree\" icon=\"/com/intellij/uiDesigner/icons/tree.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTabbedPane\" icon=\"/com/intellij/uiDesigner/icons/tabbedPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"200\" height=\"200\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JSplitPane\" icon=\"/com/intellij/uiDesigner/icons/splitPane.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"200\" height=\"200\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JSpinner\" icon=\"/com/intellij/uiDesigner/icons/spinner.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JSlider\" icon=\"/com/intellij/uiDesigner/icons/slider.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JSeparator\" icon=\"/com/intellij/uiDesigner/icons/separator.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JProgressBar\" icon=\"/com/intellij/uiDesigner/icons/progressbar.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JToolBar\" icon=\"/com/intellij/uiDesigner/icons/toolbar.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\">\n          <preferred-size width=\"-1\" height=\"20\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JToolBar$Separator\" icon=\"/com/intellij/uiDesigner/icons/toolbarSeparator.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JScrollBar\" icon=\"/com/intellij/uiDesigner/icons/scrollbar.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"0\" anchor=\"0\" fill=\"2\" />\n      </item>\n    </group>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "IntelliJBestAction.adoc",
    "content": "== IntelliJ IDEA最佳实践\n\n. Intellij IDEA for Java WEB 开发\n* 快捷键\n* 插件\n* 快速测试\n* Java工具包\n. Intellij IDEA for Scala 开发(ing)\n. Intellij IDEA for Kotlin 开发(ing)\n\nNOTE: 如无特殊说明, 本文基于Mac OS 及Intellij IDEA 2020.1.x, +\n涉及系统或版本差异时会就近补充说明, +\n总体上: Mac的**#cmd#**等价于Windows的**#ctrl#**, +\nIntellij IDEA高版本功能是兼容低版本功能的, 只是部分插件会受到一些影响\n\n=== 快捷键\n\n- 找到所有快捷键, `Help` --> `Keymap Reference`, 出现的PDF展示了当前你的编辑器的所有快捷键\n- 确实有点多, 不着急, 知道了方法, 后续只是时间问题.\n如何搜索快捷键, 参见下图\n\nimage::http://file.debuggerpowerzcy.top/power/Shortcut.png[title=如何搜索快捷键]\n\n.10个高频快捷键\n|===\n|功能 |关键词 |示例(默认)快捷键\n\n|①语句自动完成\n|Complete statement\n|cmd + shift + enter\n\n|②复写(父类)方法\n|Override methods \\| Generate\n|ctrl + O \\| ctrl + enter\n\n|③智能提示\\|纠错\n|Show Context Actions\n|ctrl + shift + alt + enter\n\n|④快速复制粘贴\n|Duplicate Line or Selection\n|cmd + D\n\n|⑤查看方法调用\n|Call Hierarchy\n|ctrl + alt + H\n\n|⑥跳转到父类申明\n|Go to Super Method\n|cmd + U\n\n|⑦跳转到子类实现\n|Go to Declaration or Usages\n|cmd + B\n\n|⑧拼接下一行\n|Join Lines\n|ctrl + shift + J\n\n|⑨优化导包\n|Optimize Imports\n|ctrl + alt + O\n\n|⑩格式化代码\n|Reformat Code\n|cmd + alt + L\n\n|更多彩蛋\n|安装插件 Key Promoter X\n|对于有快捷键的按钮, 当你点击时提示告诉你快捷键\n|===\n\n=== 插件\n\n- https://plugins.jetbrains.com/plugin/9792-key-promoter-x/[Key Promoter X]\n* 快捷键提示, 新手必备, 而老手也可以通过它得知新版IDEA的一些特性信息\n- https://plugins.jetbrains.com/plugin/10080-rainbow-brackets/[Rainbow Brackets]\n* 代码括号自动匹配, 彩板护眼\n- https://plugins.jetbrains.com/plugin/6317-lombok/[Lombok]\n* 这位都听说过吧, 没听过的要么是大佬要么改行吧\n* 采坑经验, 使用Lombok时, 尽量避免对象间继承, 如果非要继承, 应考虑@EqualsAndHashCode(callSuper = true : false)\n* 示例:\n\n[source,jave]\n----\n/**\n * balabala\n *\n * @author Mr.X\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\n@EqualsAndHashCode(callSuper = true)\npublic class PormHub extends GitHub{\n    private Boolean well = Boolean.FALSE;\n}\n----\n\n- https://plugins.jetbrains.com/plugin/7391-asciidoc/[AsciiDoc]\n* 文档编辑神器, AsciiDoc本身目标是制作大型电子书, 超越MarkDown, 本文就是用AsciiDoc书写完成的\n* **Spring**官方、**Spring-Alibaba**官方都采用AsciiDoc撰写文档, **GitHub**也支持AsciiDoc, AsciiDoc是未来的主流, MarkDown貌似要成替补了\n* 个人使用体验, 对于写技术文档, 上手快, 简洁, 本文的一个小目标就是为新手提供常用的模块, 支持ctrl + c | v\n\nimage::http://file.debuggerpowerzcy.top/power/AsciiDoc.png[title=AsciiDoc文档速览]\n\n- https://plugins.jetbrains.com/plugin/8579-translation/[Translation]\n* 作为中国程序员, 英语不会咋办?\n* 安装该插件, 选中任意文本, *ctrl + alt + T* 一键翻译\n\n- https://plugins.jetbrains.com/plugin/6725-ibatis-mybatis-mini-plugin/[iBATIS/MyBatis mini-plugin]\n* 对于采用Mybatis且保留SQL的方式, 从Mapper接口跳转到对应SQL处, 可以借助该插件完成\n* 当然现在有很多采用无SQL的方式, 参见 https://github.com/baomidou/mybatis-plus[苞米豆]\n- https://plugins.jetbrains.com/plugin/7179-maven-helper/[MavenHelper]\n* 国内Java工程多采用Maven来管理依赖, 对于一些不讲究的老项目, 依赖纠缠不清, 这个时候咋办?\n* 就这样, 凉拌吧!\n* 又或者, MavenHelper带你浴火重生, 请看下图\n\nimage::http://file.debuggerpowerzcy.top/power/MavenHelper.png[title=MavenHelper特性速览]\n\n- https://plugins.jetbrains.com/plugin/8286-sequencediagram/[SequenceDiagram]\n* 当我们跳槽后接坑时, 代码的链路是怎样的, 怎么没完没了呢?\n* 这个时候, SequenceDiagram带你一览全貌\n* 方法调用时序图出来了, 慢慢瞅吧!\n\nimage::http://file.debuggerpowerzcy.top/power/SequenceDiagram.png[title=SequenceDiagram特性速览]\n\n- https://plugins.jetbrains.com/plugin/13576-d8gerautocode/[D8gerAutoCode]\n* 作为Web开发, 当业务理解清楚后, 开发过程就可以量化如下:\n. 表设计\n. SQL -> Mapper -> Mo -> -> handler -> *Service* -> Controller\n. 自测\n. 联调\n. PM加需求, 再改一波...\n\n* 在上诉步骤中, 我认为1、2、3步是自己可以控制的, 且步骤2中除了**Service**层代码由业务决定外, 其他基本代码基本如出一辙\n* 这意味着什么?\n* 据我的观察, 1-3年的大部分程序员就在写这些重复代码, 有时写错或者抄错了, 到调试时定位到问题, 真的浪费不少时间...\n* 好在不少前辈通过创建工具, 以逆向工程方式生成``**生产环境可用的**``基础代码, 操作嘛也比较简单, 定义好SQL, 编写配置文件然后运行main方法生成\n* 我的编码生涯里也有不少这样的回忆, 只是里面仍旧有不少重复操作, 甚至多人操作时会产生冲突\n* 于是, 我从Mo出发, 写了D8gerAutoCode这个插件, 一切以表设计为核心, 你专注设计好Mo就可以, 其他基本代码使用快捷键一键搞定\n* 如果D8gerAutoCode只有这个功能, 那其实和其他大佬插件相比没有啥可比性, 大家都用习惯了, 为何要使用新的呢?\n* 重点来了: D8gerAutoCode插件专注**`解决重复`**, 在平常工作中的重复工作应该被简化, 在我看来, 程序的初衷不就是如此吗?\n* 所以, D8gerAutoCode插件还带有字符串批处理, JSON处理, MySQL处理, 字段命名处理, 针对SwaggerAPI文档的处理, 这些功能是项目开发中都会用到的, 本着一键搞定原则而开发, 欲知详情参见后文\n\nimage::http://file.debuggerpowerzcy.top/power/D8Config.png[title=插件配置]\n\nimage::http://file.debuggerpowerzcy.top/power/D8Generate.png[title=生成代码]\n\nimage::http://file.debuggerpowerzcy.top/power/D8String.png[title=字符串批处理]\n\nimage::http://file.debuggerpowerzcy.top/power/D8Format.png[title=格式化]\n\nimage::http://file.debuggerpowerzcy.top/power/D8Regrex.png[title=正则彩蛋]\n\n=== 快速测试\n\n- 基于接口进行Http测试\n- 整合Swagger-API, 代码及文档, 且支持文档界面进行调试(ing, 后续补充对应的Java实现代码)\n- 项目中涉及登录权限等问题, 在HTTP测试时应尽量模拟全, 为前端联调创造真实环境\n- 辅助工具\n* shell + python脚本\n* https://httpie.org/[httpie], 可视化格式化的HTTP请求调用工具包\n* https://github.com/kevinburke/sshpass[sshpass], 登录服务器自动输入指定密码, 可实现自动登录\n* https://github.com/caofanCPU/D8gerConcurrent[D8gerConcurrent], 支持登陆解析、自动封装Cookie、 http://www.debuggerpowerzcy.top/home/2020/05/15/EasyHttp%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/[接口并发性能测试]\n\n[source,shell script]\n----\nfunction downLoadResponse() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n}\n\nfunction downLoadExcel() {\n    echo \"执行命令内容: \\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\"\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\n}\n\nfunction show() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n}\n\n# 开发环境机器\nfunction xDev() {\n    # 借助sshpass工具, 将服务器密码保存在文件第一行, 实现自动登录; 且-t 参数支持登录后跳转到指定目录\n    sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt  ssh Mr.X@xxx.xx.xx.${1}  -t  'cd /XXX/logs/; exec $SHELL'\n}\n\n# 将HTPP请求的响应结果存入指定文件中, 示例: https-downLoadResponse https://www.baidu.com/\nalias https-downLoadResponse='downLoadResponse'\n# 在控制台展示完整的HTTP请求过程, 响应打印在控制台, 示例: https-show https://www.baidu.com/\nalias https-show='show'\n# 对于文件下载, 通过输入参数指定下载后的文件名, 示例: https-downLoadExcel https://www.baidu.com/file/123456 D8ger.zip\nalias https-downLoadExcel='downLoadExcel'\n# 对于开发测试环境多服务器, 简化为: xDev 99, 则自动登录xxx.xx.xx。99服务器\nalias 'xDev=xDev'\n----\n\nimage::http://file.debuggerpowerzcy.top/power/D8Login.png[登录获取COOKIE,并写入指定文件]\n\nimage::http://file.debuggerpowerzcy.top/power/D8Http.png[调用HTTP接口进行测试]\n\nIMPORT: 采用这种方法, 可以告别PostMan或PostWoman及其他软件了, 你只需要**Intellij IDEA** + *iterm2*|xshell + **python**环境\n\n=== Java工具包\n\n- Intellij IDEA代码简化模板, 这个技巧很香的, 比如常见的判断字符串不为空, 我只需要敲下``**fsnb**``, 就会得到如下代码\n\n[source,text]\n----\nif (StringUtils.isNotBlank(光标在这)) {\n\n}\n\n话不多说, 常用模板定义如下:\n/apim : SwaggerModel字段属性模板\n\noin  : 对象为null         ==> Objects.isNull()\nonn  : 对象不为null       ==> Objects.nonNull()\no2e  : 两对象相等          ==> Objects.equals(, )\none  : 两对象不相等        ==> !Objects.equals(, )\nfoin : 判断对象为null      ==> if (Objects.isNull()) {}\nfonn : 判断对象不为null    ==> if (Objects.nonNull()) {}\nfo2e : 判断两对象相等      ==> if (Objects.equals(, )) {}\nfone : 判断两对象不相等    ==> if (!Objects.equals(, )) {}\n\ncie  : 集合为空           ==> CollectionUtil.isEmpty()\ncne  : 集合不为空          ==> CollectionUtil.isNotEmpty()\nsib  : 字符串为空          ==> StringUtils.isBlank()\nsnb  : 字符串不为空        ==> StringUtils.isNotBlank()\nfcie : 判断集合为空        ==> if (CollectionUtil.isEmpty()){}\nfcne : 判断集合不为空      ==> if (CollectionUtil.isNotEmpty()){}\nfsib : 判断字符串为空      ==> if (StringUtils.isBlank()) {}\nfsnb : 判断字符串不为空    ==> if (StringUtils.isNotBlank()) {}\n----\n\nimage::http://file.debuggerpowerzcy.top/power/D8LiveTemplate.png[代码模板]\n\n- 高频工具包, 推荐GitHub开源项目 https://github.com/caofanCPU/D8gerStarters[D8gerStarters]\n* 通用工具包子项目 https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-common-util[``**spring-cloud-starter-d8ger-common-util**``]\n. 集合流式处理工具**CollectionUtil**, 分组、求和、排序应有尽有, 基本可以告别for循环\n. 树形处理工具**WrapTreeUtil**, 列表与树的多种转换骚操作也是应有尽有, 并且具有无侵入性, 开箱即用\n. 数字精度运算工具**NumberUtil**, 金额进度计算, 精准百分比\n. 枚举处理规范**IEnum**, 为项目打好根基, 规范枚举值用\n\n- 中间件可插拔Starters整合工具包, 推荐GitHub开源项目 https://github.com/caofanCPU/D8gerStarters[D8gerStarters]\n* 通用工具包子项目 https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-web-util[``**spring-cloud-starter-d8ger-web-util**``]\n. 整合常用中间件, 例如业务线程池、邮件、Redis缓存、RestTemplate调用、消息队列、接口响应消息转换器、SwaggerAPI文档处理器\n. 开关型可插拔, 默认有一套经过大型生产环境检验过的配置, 支持通过配置文件更改配置\n. 保留扩展点, 通过继承等方式覆盖原有组件\n\n=== 总结\n- 3个开源项目相辅相成, 目的与Spring等框架一致, 解决'最后一站'的重复问题, 以工具的使命提高编码效率, 让我们专注于业务开发\n* Intelli IDEA智能生码插件, https://plugins.jetbrains.com/plugin/13576-d8gerautocode/[D8gerAutoCode]\n* Python脚本, 解决服务器、登录以及HTTP接口测试里的重复工作, https://github.com/caofanCPU/D8gerConcurrent[D8gerConcurrent]\n* Java开发者的福利, 炒鸡香的工具集, https://github.com/caofanCPU/D8gerStarters[D8gerStarters]\n- *捐赠|Donate*, **实践撰文分享**实属不易, 您的支持能为更多省时省事的分享提速, 如果💰不行, 那就帮上面的开源项目点量⭐吧, 谢谢!\n\nimage::http://file.debuggerpowerzcy.top/power/D8WZ.png[]\n"
  },
  {
    "path": "IntelliJBestAction.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta content=\"IE=edge\" http-equiv=\"X-UA-Compatible\">\n    <meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\">\n    <meta content=\"Asciidoctor 2.0.10\" name=\"generator\">\n    <title>IntelliJ IDEA最佳实践</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\" rel=\"stylesheet\">\n    <style>\n        /* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n        /* Uncomment @import statement to use as custom stylesheet */\n        /*@import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\";*/\n        article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section {\n            display: block\n        }\n\n        audio, video {\n            display: inline-block\n        }\n\n        audio:not([controls]) {\n            display: none;\n            height: 0\n        }\n\n        html {\n            font-family: sans-serif;\n            -ms-text-size-adjust: 100%;\n            -webkit-text-size-adjust: 100%\n        }\n\n        a {\n            background: none\n        }\n\n        a:focus {\n            outline: thin dotted\n        }\n\n        a:active, a:hover {\n            outline: 0\n        }\n\n        h1 {\n            font-size: 2em;\n            margin: .67em 0\n        }\n\n        abbr[title] {\n            border-bottom: 1px dotted\n        }\n\n        b, strong {\n            font-weight: bold\n        }\n\n        dfn {\n            font-style: italic\n        }\n\n        hr {\n            -moz-box-sizing: content-box;\n            box-sizing: content-box;\n            height: 0\n        }\n\n        mark {\n            background: #ff0;\n            color: #000\n        }\n\n        code, kbd, pre, samp {\n            font-family: monospace;\n            font-size: 1em\n        }\n\n        pre {\n            white-space: pre-wrap\n        }\n\n        q {\n            quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"\n        }\n\n        small {\n            font-size: 80%\n        }\n\n        sub, sup {\n            font-size: 75%;\n            line-height: 0;\n            position: relative;\n            vertical-align: baseline\n        }\n\n        sup {\n            top: -.5em\n        }\n\n        sub {\n            bottom: -.25em\n        }\n\n        img {\n            border: 0\n        }\n\n        svg:not(:root) {\n            overflow: hidden\n        }\n\n        figure {\n            margin: 0\n        }\n\n        fieldset {\n            border: 1px solid silver;\n            margin: 0 2px;\n            padding: .35em .625em .75em\n        }\n\n        legend {\n            border: 0;\n            padding: 0\n        }\n\n        button, input, select, textarea {\n            font-family: inherit;\n            font-size: 100%;\n            margin: 0\n        }\n\n        button, input {\n            line-height: normal\n        }\n\n        button, select {\n            text-transform: none\n        }\n\n        button, html input[type=\"button\"], input[type=\"reset\"], input[type=\"submit\"] {\n            -webkit-appearance: button;\n            cursor: pointer\n        }\n\n        button[disabled], html input[disabled] {\n            cursor: default\n        }\n\n        input[type=\"checkbox\"], input[type=\"radio\"] {\n            box-sizing: border-box;\n            padding: 0\n        }\n\n        button::-moz-focus-inner, input::-moz-focus-inner {\n            border: 0;\n            padding: 0\n        }\n\n        textarea {\n            overflow: auto;\n            vertical-align: top\n        }\n\n        table {\n            border-collapse: collapse;\n            border-spacing: 0\n        }\n\n        *, *::before, *::after {\n            -moz-box-sizing: border-box;\n            -webkit-box-sizing: border-box;\n            box-sizing: border-box\n        }\n\n        html, body {\n            font-size: 100%\n        }\n\n        body {\n            background: #fff;\n            color: rgba(0, 0, 0, .8);\n            padding: 0;\n            margin: 0;\n            font-family: \"Noto Serif\", \"DejaVu Serif\", serif;\n            font-weight: 400;\n            font-style: normal;\n            line-height: 1;\n            position: relative;\n            cursor: auto;\n            tab-size: 4;\n            -moz-osx-font-smoothing: grayscale;\n            -webkit-font-smoothing: antialiased\n        }\n\n        a:hover {\n            cursor: pointer\n        }\n\n        img, object, embed {\n            max-width: 100%;\n            height: auto\n        }\n\n        object, embed {\n            height: 100%\n        }\n\n        img {\n            -ms-interpolation-mode: bicubic\n        }\n\n        .left {\n            float: left !important\n        }\n\n        .right {\n            float: right !important\n        }\n\n        .text-left {\n            text-align: left !important\n        }\n\n        .text-right {\n            text-align: right !important\n        }\n\n        .text-center {\n            text-align: center !important\n        }\n\n        .text-justify {\n            text-align: justify !important\n        }\n\n        .hide {\n            display: none\n        }\n\n        img, object, svg {\n            display: inline-block;\n            vertical-align: middle\n        }\n\n        textarea {\n            height: auto;\n            min-height: 50px\n        }\n\n        select {\n            width: 100%\n        }\n\n        .center {\n            margin-left: auto;\n            margin-right: auto\n        }\n\n        .stretch {\n            width: 100%\n        }\n\n        .subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title {\n            line-height: 1.45;\n            color: #7a2518;\n            font-weight: 400;\n            margin-top: 0;\n            margin-bottom: .25em\n        }\n\n        div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td {\n            margin: 0;\n            padding: 0;\n            direction: ltr\n        }\n\n        a {\n            color: #2156a5;\n            text-decoration: underline;\n            line-height: inherit\n        }\n\n        a:hover, a:focus {\n            color: #1d4b8f\n        }\n\n        a img {\n            border: 0\n        }\n\n        p {\n            font-family: inherit;\n            font-weight: 400;\n            font-size: 1em;\n            line-height: 1.6;\n            margin-bottom: 1.25em;\n            text-rendering: optimizeLegibility\n        }\n\n        p aside {\n            font-size: .875em;\n            line-height: 1.35;\n            font-style: italic\n        }\n\n        h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 {\n            font-family: \"Open Sans\", \"DejaVu Sans\", sans-serif;\n            font-weight: 300;\n            font-style: normal;\n            color: #ba3925;\n            text-rendering: optimizeLegibility;\n            margin-top: 1em;\n            margin-bottom: .5em;\n            line-height: 1.0125em\n        }\n\n        h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small {\n            font-size: 60%;\n            color: #e99b8f;\n            line-height: 0\n        }\n\n        h1 {\n            font-size: 2.125em\n        }\n\n        h2 {\n            font-size: 1.6875em\n        }\n\n        h3, #toctitle, .sidebarblock > .content > .title {\n            font-size: 1.375em\n        }\n\n        h4, h5 {\n            font-size: 1.125em\n        }\n\n        h6 {\n            font-size: 1em\n        }\n\n        hr {\n            border: solid #dddddf;\n            border-width: 1px 0 0;\n            clear: both;\n            margin: 1.25em 0 1.1875em;\n            height: 0\n        }\n\n        em, i {\n            font-style: italic;\n            line-height: inherit\n        }\n\n        strong, b {\n            font-weight: bold;\n            line-height: inherit\n        }\n\n        small {\n            font-size: 60%;\n            line-height: inherit\n        }\n\n        code {\n            font-family: \"Droid Sans Mono\", \"DejaVu Sans Mono\", monospace;\n            font-weight: 400;\n            color: rgba(0, 0, 0, .9)\n        }\n\n        ul, ol, dl {\n            font-size: 1em;\n            line-height: 1.6;\n            margin-bottom: 1.25em;\n            list-style-position: outside;\n            font-family: inherit\n        }\n\n        ul, ol {\n            margin-left: 1.5em\n        }\n\n        ul li ul, ul li ol {\n            margin-left: 1.25em;\n            margin-bottom: 0;\n            font-size: 1em\n        }\n\n        ul.square li ul, ul.circle li ul, ul.disc li ul {\n            list-style: inherit\n        }\n\n        ul.square {\n            list-style-type: square\n        }\n\n        ul.circle {\n            list-style-type: circle\n        }\n\n        ul.disc {\n            list-style-type: disc\n        }\n\n        ol li ul, ol li ol {\n            margin-left: 1.25em;\n            margin-bottom: 0\n        }\n\n        dl dt {\n            margin-bottom: .3125em;\n            font-weight: bold\n        }\n\n        dl dd {\n            margin-bottom: 1.25em\n        }\n\n        abbr, acronym {\n            text-transform: uppercase;\n            font-size: 90%;\n            color: rgba(0, 0, 0, .8);\n            border-bottom: 1px dotted #ddd;\n            cursor: help\n        }\n\n        abbr {\n            text-transform: none\n        }\n\n        blockquote {\n            margin: 0 0 1.25em;\n            padding: .5625em 1.25em 0 1.1875em;\n            border-left: 1px solid #ddd\n        }\n\n        blockquote cite {\n            display: block;\n            font-size: .9375em;\n            color: rgba(0, 0, 0, .6)\n        }\n\n        blockquote cite::before {\n            content: \"\\2014 \\0020\"\n        }\n\n        blockquote cite a, blockquote cite a:visited {\n            color: rgba(0, 0, 0, .6)\n        }\n\n        blockquote, blockquote p {\n            line-height: 1.6;\n            color: rgba(0, 0, 0, .85)\n        }\n\n        @media screen and (min-width: 768px) {\n            h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 {\n                line-height: 1.2\n            }\n\n            h1 {\n                font-size: 2.75em\n            }\n\n            h2 {\n                font-size: 2.3125em\n            }\n\n            h3, #toctitle, .sidebarblock > .content > .title {\n                font-size: 1.6875em\n            }\n\n            h4 {\n                font-size: 1.4375em\n            }\n        }\n\n        table {\n            background: #fff;\n            margin-bottom: 1.25em;\n            border: solid 1px #dedede\n        }\n\n        table thead, table tfoot {\n            background: #f7f8f7\n        }\n\n        table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td {\n            padding: .5em .625em .625em;\n            font-size: inherit;\n            color: rgba(0, 0, 0, .8);\n            text-align: left\n        }\n\n        table tr th, table tr td {\n            padding: .5625em .625em;\n            font-size: inherit;\n            color: rgba(0, 0, 0, .8)\n        }\n\n        table tr.even, table tr.alt {\n            background: #f8f8f7\n        }\n\n        table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td {\n            display: table-cell;\n            line-height: 1.6\n        }\n\n        h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 {\n            line-height: 1.2;\n            word-spacing: -.05em\n        }\n\n        h1 strong, h2 strong, h3 strong, #toctitle strong, .sidebarblock > .content > .title strong, h4 strong, h5 strong, h6 strong {\n            font-weight: 400\n        }\n\n        .clearfix::before, .clearfix::after, .float-group::before, .float-group::after {\n            content: \" \";\n            display: table\n        }\n\n        .clearfix::after, .float-group::after {\n            clear: both\n        }\n\n        :not(pre):not([class^=L]) > code {\n            font-size: .9375em;\n            font-style: normal !important;\n            letter-spacing: 0;\n            padding: .1em .5ex;\n            word-spacing: -.15em;\n            background: #f7f7f8;\n            -webkit-border-radius: 4px;\n            border-radius: 4px;\n            line-height: 1.45;\n            text-rendering: optimizeSpeed;\n            word-wrap: break-word\n        }\n\n        :not(pre) > code.nobreak {\n            word-wrap: normal\n        }\n\n        :not(pre) > code.nowrap {\n            white-space: nowrap\n        }\n\n        pre {\n            color: rgba(0, 0, 0, .9);\n            font-family: \"Droid Sans Mono\", \"DejaVu Sans Mono\", monospace;\n            line-height: 1.45;\n            text-rendering: optimizeSpeed\n        }\n\n        pre code, pre pre {\n            color: inherit;\n            font-size: inherit;\n            line-height: inherit\n        }\n\n        pre > code {\n            display: block\n        }\n\n        pre.nowrap, pre.nowrap pre {\n            white-space: pre;\n            word-wrap: normal\n        }\n\n        em em {\n            font-style: normal\n        }\n\n        strong strong {\n            font-weight: 400\n        }\n\n        .keyseq {\n            color: rgba(51, 51, 51, .8)\n        }\n\n        kbd {\n            font-family: \"Droid Sans Mono\", \"DejaVu Sans Mono\", monospace;\n            display: inline-block;\n            color: rgba(0, 0, 0, .8);\n            font-size: .65em;\n            line-height: 1.45;\n            background: #f7f7f7;\n            border: 1px solid #ccc;\n            -webkit-border-radius: 3px;\n            border-radius: 3px;\n            -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 0 0 .1em white inset;\n            box-shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 0 0 .1em #fff inset;\n            margin: 0 .15em;\n            padding: .2em .5em;\n            vertical-align: middle;\n            position: relative;\n            top: -.1em;\n            white-space: nowrap\n        }\n\n        .keyseq kbd:first-child {\n            margin-left: 0\n        }\n\n        .keyseq kbd:last-child {\n            margin-right: 0\n        }\n\n        .menuseq, .menuref {\n            color: #000\n        }\n\n        .menuseq b:not(.caret), .menuref {\n            font-weight: inherit\n        }\n\n        .menuseq {\n            word-spacing: -.02em\n        }\n\n        .menuseq b.caret {\n            font-size: 1.25em;\n            line-height: .8\n        }\n\n        .menuseq i.caret {\n            font-weight: bold;\n            text-align: center;\n            width: .45em\n        }\n\n        b.button::before, b.button::after {\n            position: relative;\n            top: -1px;\n            font-weight: 400\n        }\n\n        b.button::before {\n            content: \"[\";\n            padding: 0 3px 0 2px\n        }\n\n        b.button::after {\n            content: \"]\";\n            padding: 0 2px 0 3px\n        }\n\n        p a > code:hover {\n            color: rgba(0, 0, 0, .9)\n        }\n\n        #header, #content, #footnotes, #footer {\n            width: 100%;\n            margin-left: auto;\n            margin-right: auto;\n            margin-top: 0;\n            margin-bottom: 0;\n            max-width: 62.5em;\n            *zoom: 1;\n            position: relative;\n            padding-left: .9375em;\n            padding-right: .9375em\n        }\n\n        #header::before, #header::after, #content::before, #content::after, #footnotes::before, #footnotes::after, #footer::before, #footer::after {\n            content: \" \";\n            display: table\n        }\n\n        #header::after, #content::after, #footnotes::after, #footer::after {\n            clear: both\n        }\n\n        #content {\n            margin-top: 1.25em\n        }\n\n        #content::before {\n            content: none\n        }\n\n        #header > h1:first-child {\n            color: rgba(0, 0, 0, .85);\n            margin-top: 2.25rem;\n            margin-bottom: 0\n        }\n\n        #header > h1:first-child + #toc {\n            margin-top: 8px;\n            border-top: 1px solid #dddddf\n        }\n\n        #header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) {\n            border-bottom: 1px solid #dddddf;\n            padding-bottom: 8px\n        }\n\n        #header .details {\n            border-bottom: 1px solid #dddddf;\n            line-height: 1.45;\n            padding-top: .25em;\n            padding-bottom: .25em;\n            padding-left: .25em;\n            color: rgba(0, 0, 0, .6);\n            display: -ms-flexbox;\n            display: -webkit-flex;\n            display: flex;\n            -ms-flex-flow: row wrap;\n            -webkit-flex-flow: row wrap;\n            flex-flow: row wrap\n        }\n\n        #header .details span:first-child {\n            margin-left: -.125em\n        }\n\n        #header .details span.email a {\n            color: rgba(0, 0, 0, .85)\n        }\n\n        #header .details br {\n            display: none\n        }\n\n        #header .details br + span::before {\n            content: \"\\00a0\\2013\\00a0\"\n        }\n\n        #header .details br + span.author::before {\n            content: \"\\00a0\\22c5\\00a0\";\n            color: rgba(0, 0, 0, .85)\n        }\n\n        #header .details br + span#revremark::before {\n            content: \"\\00a0|\\00a0\"\n        }\n\n        #header #revnumber {\n            text-transform: capitalize\n        }\n\n        #header #revnumber::after {\n            content: \"\\00a0\"\n        }\n\n        #content > h1:first-child:not([class]) {\n            color: rgba(0, 0, 0, .85);\n            border-bottom: 1px solid #dddddf;\n            padding-bottom: 8px;\n            margin-top: 0;\n            padding-top: 1rem;\n            margin-bottom: 1.25rem\n        }\n\n        #toc {\n            border-bottom: 1px solid #e7e7e9;\n            padding-bottom: .5em\n        }\n\n        #toc > ul {\n            margin-left: .125em\n        }\n\n        #toc ul.sectlevel0 > li > a {\n            font-style: italic\n        }\n\n        #toc ul.sectlevel0 ul.sectlevel1 {\n            margin: .5em 0\n        }\n\n        #toc ul {\n            font-family: \"Open Sans\", \"DejaVu Sans\", sans-serif;\n            list-style-type: none\n        }\n\n        #toc li {\n            line-height: 1.3334;\n            margin-top: .3334em\n        }\n\n        #toc a {\n            text-decoration: none\n        }\n\n        #toc a:active {\n            text-decoration: underline\n        }\n\n        #toctitle {\n            color: #7a2518;\n            font-size: 1.2em\n        }\n\n        @media screen and (min-width: 768px) {\n            #toctitle {\n                font-size: 1.375em\n            }\n\n            body.toc2 {\n                padding-left: 15em;\n                padding-right: 0\n            }\n\n            #toc.toc2 {\n                margin-top: 0 !important;\n                background: #f8f8f7;\n                position: fixed;\n                width: 15em;\n                left: 0;\n                top: 0;\n                border-right: 1px solid #e7e7e9;\n                border-top-width: 0 !important;\n                border-bottom-width: 0 !important;\n                z-index: 1000;\n                padding: 1.25em 1em;\n                height: 100%;\n                overflow: auto\n            }\n\n            #toc.toc2 #toctitle {\n                margin-top: 0;\n                margin-bottom: .8rem;\n                font-size: 1.2em\n            }\n\n            #toc.toc2 > ul {\n                font-size: .9em;\n                margin-bottom: 0\n            }\n\n            #toc.toc2 ul ul {\n                margin-left: 0;\n                padding-left: 1em\n            }\n\n            #toc.toc2 ul.sectlevel0 ul.sectlevel1 {\n                padding-left: 0;\n                margin-top: .5em;\n                margin-bottom: .5em\n            }\n\n            body.toc2.toc-right {\n                padding-left: 0;\n                padding-right: 15em\n            }\n\n            body.toc2.toc-right #toc.toc2 {\n                border-right-width: 0;\n                border-left: 1px solid #e7e7e9;\n                left: auto;\n                right: 0\n            }\n        }\n\n        @media screen and (min-width: 1280px) {\n            body.toc2 {\n                padding-left: 20em;\n                padding-right: 0\n            }\n\n            #toc.toc2 {\n                width: 20em\n            }\n\n            #toc.toc2 #toctitle {\n                font-size: 1.375em\n            }\n\n            #toc.toc2 > ul {\n                font-size: .95em\n            }\n\n            #toc.toc2 ul ul {\n                padding-left: 1.25em\n            }\n\n            body.toc2.toc-right {\n                padding-left: 0;\n                padding-right: 20em\n            }\n        }\n\n        #content #toc {\n            border-style: solid;\n            border-width: 1px;\n            border-color: #e0e0dc;\n            margin-bottom: 1.25em;\n            padding: 1.25em;\n            background: #f8f8f7;\n            -webkit-border-radius: 4px;\n            border-radius: 4px\n        }\n\n        #content #toc > :first-child {\n            margin-top: 0\n        }\n\n        #content #toc > :last-child {\n            margin-bottom: 0\n        }\n\n        #footer {\n            max-width: 100%;\n            background: rgba(0, 0, 0, .8);\n            padding: 1.25em\n        }\n\n        #footer-text {\n            color: rgba(255, 255, 255, .8);\n            line-height: 1.44\n        }\n\n        #content {\n            margin-bottom: .625em\n        }\n\n        .sect1 {\n            padding-bottom: .625em\n        }\n\n        @media screen and (min-width: 768px) {\n            #content {\n                margin-bottom: 1.25em\n            }\n\n            .sect1 {\n                padding-bottom: 1.25em\n            }\n        }\n\n        .sect1:last-child {\n            padding-bottom: 0\n        }\n\n        .sect1 + .sect1 {\n            border-top: 1px solid #e7e7e9\n        }\n\n        #content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor {\n            position: absolute;\n            z-index: 1001;\n            width: 1.5ex;\n            margin-left: -1.5ex;\n            display: block;\n            text-decoration: none !important;\n            visibility: hidden;\n            text-align: center;\n            font-weight: 400\n        }\n\n        #content h1 > a.anchor::before, h2 > a.anchor::before, h3 > a.anchor::before, #toctitle > a.anchor::before, .sidebarblock > .content > .title > a.anchor::before, h4 > a.anchor::before, h5 > a.anchor::before, h6 > a.anchor::before {\n            content: \"\\00A7\";\n            font-size: .85em;\n            display: block;\n            padding-top: .1em\n        }\n\n        #content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover {\n            visibility: visible\n        }\n\n        #content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link {\n            color: #ba3925;\n            text-decoration: none\n        }\n\n        #content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover {\n            color: #a53221\n        }\n\n        details, .audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock {\n            margin-bottom: 1.25em\n        }\n\n        details > summary:first-of-type {\n            cursor: pointer;\n            display: list-item;\n            outline: none;\n            margin-bottom: .75em\n        }\n\n        .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title {\n            text-rendering: optimizeLegibility;\n            text-align: left;\n            font-family: \"Noto Serif\", \"DejaVu Serif\", serif;\n            font-size: 1rem;\n            font-style: italic\n        }\n\n        table.tableblock.fit-content > caption.title {\n            white-space: nowrap;\n            width: 0\n        }\n\n        .paragraph.lead > p, #preamble > .sectionbody > [class=\"paragraph\"]:first-of-type p {\n            font-size: 1.21875em;\n            line-height: 1.6;\n            color: rgba(0, 0, 0, .85)\n        }\n\n        table.tableblock #preamble > .sectionbody > [class=\"paragraph\"]:first-of-type p {\n            font-size: inherit\n        }\n\n        .admonitionblock > table {\n            border-collapse: separate;\n            border: 0;\n            background: none;\n            width: 100%\n        }\n\n        .admonitionblock > table td.icon {\n            text-align: center;\n            width: 80px\n        }\n\n        .admonitionblock > table td.icon img {\n            max-width: none\n        }\n\n        .admonitionblock > table td.icon .title {\n            font-weight: bold;\n            font-family: \"Open Sans\", \"DejaVu Sans\", sans-serif;\n            text-transform: uppercase\n        }\n\n        .admonitionblock > table td.content {\n            padding-left: 1.125em;\n            padding-right: 1.25em;\n            border-left: 1px solid #dddddf;\n            color: rgba(0, 0, 0, .6)\n        }\n\n        .admonitionblock > table td.content > :last-child > :last-child {\n            margin-bottom: 0\n        }\n\n        .exampleblock > .content {\n            border-style: solid;\n            border-width: 1px;\n            border-color: #e6e6e6;\n            margin-bottom: 1.25em;\n            padding: 1.25em;\n            background: #fff;\n            -webkit-border-radius: 4px;\n            border-radius: 4px\n        }\n\n        .exampleblock > .content > :first-child {\n            margin-top: 0\n        }\n\n        .exampleblock > .content > :last-child {\n            margin-bottom: 0\n        }\n\n        .sidebarblock {\n            border-style: solid;\n            border-width: 1px;\n            border-color: #dbdbd6;\n            margin-bottom: 1.25em;\n            padding: 1.25em;\n            background: #f3f3f2;\n            -webkit-border-radius: 4px;\n            border-radius: 4px\n        }\n\n        .sidebarblock > :first-child {\n            margin-top: 0\n        }\n\n        .sidebarblock > :last-child {\n            margin-bottom: 0\n        }\n\n        .sidebarblock > .content > .title {\n            color: #7a2518;\n            margin-top: 0;\n            text-align: center\n        }\n\n        .exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child {\n            margin-bottom: 0\n        }\n\n        .literalblock pre, .listingblock > .content > pre {\n            -webkit-border-radius: 4px;\n            border-radius: 4px;\n            word-wrap: break-word;\n            overflow-x: auto;\n            padding: 1em;\n            font-size: .8125em\n        }\n\n        @media screen and (min-width: 768px) {\n            .literalblock pre, .listingblock > .content > pre {\n                font-size: .90625em\n            }\n        }\n\n        @media screen and (min-width: 1280px) {\n            .literalblock pre, .listingblock > .content > pre {\n                font-size: 1em\n            }\n        }\n\n        .literalblock pre, .listingblock > .content > pre:not(.highlight), .listingblock > .content > pre[class=\"highlight\"], .listingblock > .content > pre[class^=\"highlight \"] {\n            background: #f7f7f8\n        }\n\n        .literalblock.output pre {\n            color: #f7f7f8;\n            background: rgba(0, 0, 0, .9)\n        }\n\n        .listingblock > .content {\n            position: relative\n        }\n\n        .listingblock code[data-lang]::before {\n            display: none;\n            content: attr(data-lang);\n            position: absolute;\n            font-size: .75em;\n            top: .425rem;\n            right: .5rem;\n            line-height: 1;\n            text-transform: uppercase;\n            color: inherit;\n            opacity: .5\n        }\n\n        .listingblock:hover code[data-lang]::before {\n            display: block\n        }\n\n        .listingblock.terminal pre .command::before {\n            content: attr(data-prompt);\n            padding-right: .5em;\n            color: inherit;\n            opacity: .5\n        }\n\n        .listingblock.terminal pre .command:not([data-prompt])::before {\n            content: \"$\"\n        }\n\n        .listingblock pre.highlightjs {\n            padding: 0\n        }\n\n        .listingblock pre.highlightjs > code {\n            padding: 1em;\n            -webkit-border-radius: 4px;\n            border-radius: 4px\n        }\n\n        .listingblock pre.prettyprint {\n            border-width: 0\n        }\n\n        .prettyprint {\n            background: #f7f7f8\n        }\n\n        pre.prettyprint .linenums {\n            line-height: 1.45;\n            margin-left: 2em\n        }\n\n        pre.prettyprint li {\n            background: none;\n            list-style-type: inherit;\n            padding-left: 0\n        }\n\n        pre.prettyprint li code[data-lang]::before {\n            opacity: 1\n        }\n\n        pre.prettyprint li:not(:first-child) code[data-lang]::before {\n            display: none\n        }\n\n        table.linenotable {\n            border-collapse: separate;\n            border: 0;\n            margin-bottom: 0;\n            background: none\n        }\n\n        table.linenotable td[class] {\n            color: inherit;\n            vertical-align: top;\n            padding: 0;\n            line-height: inherit;\n            white-space: normal\n        }\n\n        table.linenotable td.code {\n            padding-left: .75em\n        }\n\n        table.linenotable td.linenos {\n            border-right: 1px solid currentColor;\n            opacity: .35;\n            padding-right: .5em\n        }\n\n        pre.pygments .lineno {\n            border-right: 1px solid currentColor;\n            opacity: .35;\n            display: inline-block;\n            margin-right: .75em\n        }\n\n        pre.pygments .lineno::before {\n            content: \"\";\n            margin-right: -.125em\n        }\n\n        .quoteblock {\n            margin: 0 1em 1.25em 1.5em;\n            display: table\n        }\n\n        .quoteblock:not(.excerpt) > .title {\n            margin-left: -1.5em;\n            margin-bottom: .75em\n        }\n\n        .quoteblock blockquote, .quoteblock p {\n            color: rgba(0, 0, 0, .85);\n            font-size: 1.15rem;\n            line-height: 1.75;\n            word-spacing: .1em;\n            letter-spacing: 0;\n            font-style: italic;\n            text-align: justify\n        }\n\n        .quoteblock blockquote {\n            margin: 0;\n            padding: 0;\n            border: 0\n        }\n\n        .quoteblock blockquote::before {\n            content: \"\\201c\";\n            float: left;\n            font-size: 2.75em;\n            font-weight: bold;\n            line-height: .6em;\n            margin-left: -.6em;\n            color: #7a2518;\n            text-shadow: 0 1px 2px rgba(0, 0, 0, .1)\n        }\n\n        .quoteblock blockquote > .paragraph:last-child p {\n            margin-bottom: 0\n        }\n\n        .quoteblock .attribution {\n            margin-top: .75em;\n            margin-right: .5ex;\n            text-align: right\n        }\n\n        .verseblock {\n            margin: 0 1em 1.25em\n        }\n\n        .verseblock pre {\n            font-family: \"Open Sans\", \"DejaVu Sans\", sans;\n            font-size: 1.15rem;\n            color: rgba(0, 0, 0, .85);\n            font-weight: 300;\n            text-rendering: optimizeLegibility\n        }\n\n        .verseblock pre strong {\n            font-weight: 400\n        }\n\n        .verseblock .attribution {\n            margin-top: 1.25rem;\n            margin-left: .5ex\n        }\n\n        .quoteblock .attribution, .verseblock .attribution {\n            font-size: .9375em;\n            line-height: 1.45;\n            font-style: italic\n        }\n\n        .quoteblock .attribution br, .verseblock .attribution br {\n            display: none\n        }\n\n        .quoteblock .attribution cite, .verseblock .attribution cite {\n            display: block;\n            letter-spacing: -.025em;\n            color: rgba(0, 0, 0, .6)\n        }\n\n        .quoteblock.abstract blockquote::before, .quoteblock.excerpt blockquote::before, .quoteblock .quoteblock blockquote::before {\n            display: none\n        }\n\n        .quoteblock.abstract blockquote, .quoteblock.abstract p, .quoteblock.excerpt blockquote, .quoteblock.excerpt p, .quoteblock .quoteblock blockquote, .quoteblock .quoteblock p {\n            line-height: 1.6;\n            word-spacing: 0\n        }\n\n        .quoteblock.abstract {\n            margin: 0 1em 1.25em;\n            display: block\n        }\n\n        .quoteblock.abstract > .title {\n            margin: 0 0 .375em;\n            font-size: 1.15em;\n            text-align: center\n        }\n\n        .quoteblock.excerpt > blockquote, .quoteblock .quoteblock {\n            padding: 0 0 .25em 1em;\n            border-left: .25em solid #dddddf\n        }\n\n        .quoteblock.excerpt, .quoteblock .quoteblock {\n            margin-left: 0\n        }\n\n        .quoteblock.excerpt blockquote, .quoteblock.excerpt p, .quoteblock .quoteblock blockquote, .quoteblock .quoteblock p {\n            color: inherit;\n            font-size: 1.0625rem\n        }\n\n        .quoteblock.excerpt .attribution, .quoteblock .quoteblock .attribution {\n            color: inherit;\n            text-align: left;\n            margin-right: 0\n        }\n\n        table.tableblock {\n            max-width: 100%;\n            border-collapse: separate\n        }\n\n        p.tableblock:last-child {\n            margin-bottom: 0\n        }\n\n        td.tableblock > .content > :last-child {\n            margin-bottom: -1.25em\n        }\n\n        td.tableblock > .content > :last-child.sidebarblock {\n            margin-bottom: 0\n        }\n\n        table.tableblock, th.tableblock, td.tableblock {\n            border: 0 solid #dedede\n        }\n\n        table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock {\n            border-width: 0 1px 1px 0\n        }\n\n        table.grid-all > tfoot > tr > .tableblock {\n            border-width: 1px 1px 0 0\n        }\n\n        table.grid-cols > * > tr > .tableblock {\n            border-width: 0 1px 0 0\n        }\n\n        table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock {\n            border-width: 0 0 1px\n        }\n\n        table.grid-rows > tfoot > tr > .tableblock {\n            border-width: 1px 0 0\n        }\n\n        table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child {\n            border-right-width: 0\n        }\n\n        table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock {\n            border-bottom-width: 0\n        }\n\n        table.frame-all {\n            border-width: 1px\n        }\n\n        table.frame-sides {\n            border-width: 0 1px\n        }\n\n        table.frame-topbot, table.frame-ends {\n            border-width: 1px 0\n        }\n\n        table.stripes-all tr, table.stripes-odd tr:nth-of-type(odd), table.stripes-even tr:nth-of-type(even), table.stripes-hover tr:hover {\n            background: #f8f8f7\n        }\n\n        th.halign-left, td.halign-left {\n            text-align: left\n        }\n\n        th.halign-right, td.halign-right {\n            text-align: right\n        }\n\n        th.halign-center, td.halign-center {\n            text-align: center\n        }\n\n        th.valign-top, td.valign-top {\n            vertical-align: top\n        }\n\n        th.valign-bottom, td.valign-bottom {\n            vertical-align: bottom\n        }\n\n        th.valign-middle, td.valign-middle {\n            vertical-align: middle\n        }\n\n        table thead th, table tfoot th {\n            font-weight: bold\n        }\n\n        tbody tr th {\n            display: table-cell;\n            line-height: 1.6;\n            background: #f7f8f7\n        }\n\n        tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p {\n            color: rgba(0, 0, 0, .8);\n            font-weight: bold\n        }\n\n        p.tableblock > code:only-child {\n            background: none;\n            padding: 0\n        }\n\n        p.tableblock {\n            font-size: 1em\n        }\n\n        ol {\n            margin-left: 1.75em\n        }\n\n        ul li ol {\n            margin-left: 1.5em\n        }\n\n        dl dd {\n            margin-left: 1.125em\n        }\n\n        dl dd:last-child, dl dd:last-child > :last-child {\n            margin-bottom: 0\n        }\n\n        ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist {\n            margin-bottom: .625em\n        }\n\n        ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled {\n            list-style-type: none\n        }\n\n        ul.no-bullet, ol.no-bullet, ol.unnumbered {\n            margin-left: .625em\n        }\n\n        ul.unstyled, ol.unstyled {\n            margin-left: 0\n        }\n\n        ul.checklist {\n            margin-left: .625em\n        }\n\n        ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child {\n            width: 1.25em;\n            font-size: .8em;\n            position: relative;\n            bottom: .125em\n        }\n\n        ul.checklist li > p:first-child > input[type=\"checkbox\"]:first-child {\n            margin-right: .25em\n        }\n\n        ul.inline {\n            display: -ms-flexbox;\n            display: -webkit-box;\n            display: flex;\n            -ms-flex-flow: row wrap;\n            -webkit-flex-flow: row wrap;\n            flex-flow: row wrap;\n            list-style: none;\n            margin: 0 0 .625em -1.25em\n        }\n\n        ul.inline > li {\n            margin-left: 1.25em\n        }\n\n        .unstyled dl dt {\n            font-weight: 400;\n            font-style: normal\n        }\n\n        ol.arabic {\n            list-style-type: decimal\n        }\n\n        ol.decimal {\n            list-style-type: decimal-leading-zero\n        }\n\n        ol.loweralpha {\n            list-style-type: lower-alpha\n        }\n\n        ol.upperalpha {\n            list-style-type: upper-alpha\n        }\n\n        ol.lowerroman {\n            list-style-type: lower-roman\n        }\n\n        ol.upperroman {\n            list-style-type: upper-roman\n        }\n\n        ol.lowergreek {\n            list-style-type: lower-greek\n        }\n\n        .hdlist > table, .colist > table {\n            border: 0;\n            background: none\n        }\n\n        .hdlist > table > tbody > tr, .colist > table > tbody > tr {\n            background: none\n        }\n\n        td.hdlist1, td.hdlist2 {\n            vertical-align: top;\n            padding: 0 .625em\n        }\n\n        td.hdlist1 {\n            font-weight: bold;\n            padding-bottom: 1.25em\n        }\n\n        .literalblock + .colist, .listingblock + .colist {\n            margin-top: -.5em\n        }\n\n        .colist td:not([class]):first-child {\n            padding: .4em .75em 0;\n            line-height: 1;\n            vertical-align: top\n        }\n\n        .colist td:not([class]):first-child img {\n            max-width: none\n        }\n\n        .colist td:not([class]):last-child {\n            padding: .25em 0\n        }\n\n        .thumb, .th {\n            line-height: 0;\n            display: inline-block;\n            border: solid 4px #fff;\n            -webkit-box-shadow: 0 0 0 1px #ddd;\n            box-shadow: 0 0 0 1px #ddd\n        }\n\n        .imageblock.left {\n            margin: .25em .625em 1.25em 0\n        }\n\n        .imageblock.right {\n            margin: .25em 0 1.25em .625em\n        }\n\n        .imageblock > .title {\n            margin-bottom: 0\n        }\n\n        .imageblock.thumb, .imageblock.th {\n            border-width: 6px\n        }\n\n        .imageblock.thumb > .title, .imageblock.th > .title {\n            padding: 0 .125em\n        }\n\n        .image.left, .image.right {\n            margin-top: .25em;\n            margin-bottom: .25em;\n            display: inline-block;\n            line-height: 0\n        }\n\n        .image.left {\n            margin-right: .625em\n        }\n\n        .image.right {\n            margin-left: .625em\n        }\n\n        a.image {\n            text-decoration: none;\n            display: inline-block\n        }\n\n        a.image object {\n            pointer-events: none\n        }\n\n        sup.footnote, sup.footnoteref {\n            font-size: .875em;\n            position: static;\n            vertical-align: super\n        }\n\n        sup.footnote a, sup.footnoteref a {\n            text-decoration: none\n        }\n\n        sup.footnote a:active, sup.footnoteref a:active {\n            text-decoration: underline\n        }\n\n        #footnotes {\n            padding-top: .75em;\n            padding-bottom: .75em;\n            margin-bottom: .625em\n        }\n\n        #footnotes hr {\n            width: 20%;\n            min-width: 6.25em;\n            margin: -.25em 0 .75em;\n            border-width: 1px 0 0\n        }\n\n        #footnotes .footnote {\n            padding: 0 .375em 0 .225em;\n            line-height: 1.3334;\n            font-size: .875em;\n            margin-left: 1.2em;\n            margin-bottom: .2em\n        }\n\n        #footnotes .footnote a:first-of-type {\n            font-weight: bold;\n            text-decoration: none;\n            margin-left: -1.05em\n        }\n\n        #footnotes .footnote:last-of-type {\n            margin-bottom: 0\n        }\n\n        #content #footnotes {\n            margin-top: -.625em;\n            margin-bottom: 0;\n            padding: .75em 0\n        }\n\n        .gist .file-data > table {\n            border: 0;\n            background: #fff;\n            width: 100%;\n            margin-bottom: 0\n        }\n\n        .gist .file-data > table td.line-data {\n            width: 99%\n        }\n\n        div.unbreakable {\n            page-break-inside: avoid\n        }\n\n        .big {\n            font-size: larger\n        }\n\n        .small {\n            font-size: smaller\n        }\n\n        .underline {\n            text-decoration: underline\n        }\n\n        .overline {\n            text-decoration: overline\n        }\n\n        .line-through {\n            text-decoration: line-through\n        }\n\n        .aqua {\n            color: #00bfbf\n        }\n\n        .aqua-background {\n            background: #00fafa\n        }\n\n        .black {\n            color: #000\n        }\n\n        .black-background {\n            background: #000\n        }\n\n        .blue {\n            color: #0000bf\n        }\n\n        .blue-background {\n            background: #0000fa\n        }\n\n        .fuchsia {\n            color: #bf00bf\n        }\n\n        .fuchsia-background {\n            background: #fa00fa\n        }\n\n        .gray {\n            color: #606060\n        }\n\n        .gray-background {\n            background: #7d7d7d\n        }\n\n        .green {\n            color: #006000\n        }\n\n        .green-background {\n            background: #007d00\n        }\n\n        .lime {\n            color: #00bf00\n        }\n\n        .lime-background {\n            background: #00fa00\n        }\n\n        .maroon {\n            color: #600000\n        }\n\n        .maroon-background {\n            background: #7d0000\n        }\n\n        .navy {\n            color: #000060\n        }\n\n        .navy-background {\n            background: #00007d\n        }\n\n        .olive {\n            color: #606000\n        }\n\n        .olive-background {\n            background: #7d7d00\n        }\n\n        .purple {\n            color: #600060\n        }\n\n        .purple-background {\n            background: #7d007d\n        }\n\n        .red {\n            color: #bf0000\n        }\n\n        .red-background {\n            background: #fa0000\n        }\n\n        .silver {\n            color: #909090\n        }\n\n        .silver-background {\n            background: #bcbcbc\n        }\n\n        .teal {\n            color: #006060\n        }\n\n        .teal-background {\n            background: #007d7d\n        }\n\n        .white {\n            color: #bfbfbf\n        }\n\n        .white-background {\n            background: #fafafa\n        }\n\n        .yellow {\n            color: #bfbf00\n        }\n\n        .yellow-background {\n            background: #fafa00\n        }\n\n        span.icon > .fa {\n            cursor: default\n        }\n\n        a span.icon > .fa {\n            cursor: inherit\n        }\n\n        .admonitionblock td.icon [class^=\"fa icon-\"] {\n            font-size: 2.5em;\n            text-shadow: 1px 1px 2px rgba(0, 0, 0, .5);\n            cursor: default\n        }\n\n        .admonitionblock td.icon .icon-note::before {\n            content: \"\\f05a\";\n            color: #19407c\n        }\n\n        .admonitionblock td.icon .icon-tip::before {\n            content: \"\\f0eb\";\n            text-shadow: 1px 1px 2px rgba(155, 155, 0, .8);\n            color: #111\n        }\n\n        .admonitionblock td.icon .icon-warning::before {\n            content: \"\\f071\";\n            color: #bf6900\n        }\n\n        .admonitionblock td.icon .icon-caution::before {\n            content: \"\\f06d\";\n            color: #bf3400\n        }\n\n        .admonitionblock td.icon .icon-important::before {\n            content: \"\\f06a\";\n            color: #bf0000\n        }\n\n        .conum[data-value] {\n            display: inline-block;\n            color: #fff !important;\n            background: rgba(0, 0, 0, .8);\n            -webkit-border-radius: 100px;\n            border-radius: 100px;\n            text-align: center;\n            font-size: .75em;\n            width: 1.67em;\n            height: 1.67em;\n            line-height: 1.67em;\n            font-family: \"Open Sans\", \"DejaVu Sans\", sans-serif;\n            font-style: normal;\n            font-weight: bold\n        }\n\n        .conum[data-value] * {\n            color: #fff !important\n        }\n\n        .conum[data-value] + b {\n            display: none\n        }\n\n        .conum[data-value]::after {\n            content: attr(data-value)\n        }\n\n        pre .conum[data-value] {\n            position: relative;\n            top: -.125em\n        }\n\n        b.conum * {\n            color: inherit !important\n        }\n\n        .conum:not([data-value]):empty {\n            display: none\n        }\n\n        dt, th.tableblock, td.content, div.footnote {\n            text-rendering: optimizeLegibility\n        }\n\n        h1, h2, p, td.content, span.alt {\n            letter-spacing: -.01em\n        }\n\n        p strong, td.content strong, div.footnote strong {\n            letter-spacing: -.005em\n        }\n\n        p, blockquote, dt, td.content, span.alt {\n            font-size: 1.0625rem\n        }\n\n        p {\n            margin-bottom: 1.25rem\n        }\n\n        .sidebarblock p, .sidebarblock dt, .sidebarblock td.content, p.tableblock {\n            font-size: 1em\n        }\n\n        .exampleblock > .content {\n            background: #fffef7;\n            border-color: #e0e0dc;\n            -webkit-box-shadow: 0 1px 4px #e0e0dc;\n            box-shadow: 0 1px 4px #e0e0dc\n        }\n\n        .print-only {\n            display: none !important\n        }\n\n        @page {\n            margin: 1.25cm .75cm\n        }\n\n        @media print {\n            * {\n                -webkit-box-shadow: none !important;\n                box-shadow: none !important;\n                text-shadow: none !important\n            }\n\n            html {\n                font-size: 80%\n            }\n\n            a {\n                color: inherit !important;\n                text-decoration: underline !important\n            }\n\n            a.bare, a[href^=\"#\"], a[href^=\"mailto:\"] {\n                text-decoration: none !important\n            }\n\n            a[href^=\"http:\"]:not(.bare)::after, a[href^=\"https:\"]:not(.bare)::after {\n                content: \"(\" attr(href) \")\";\n                display: inline-block;\n                font-size: .875em;\n                padding-left: .25em\n            }\n\n            abbr[title]::after {\n                content: \" (\" attr(title) \")\"\n            }\n\n            pre, blockquote, tr, img, object, svg {\n                page-break-inside: avoid\n            }\n\n            thead {\n                display: table-header-group\n            }\n\n            svg {\n                max-width: 100%\n            }\n\n            p, blockquote, dt, td.content {\n                font-size: 1em;\n                orphans: 3;\n                widows: 3\n            }\n\n            h2, h3, #toctitle, .sidebarblock > .content > .title {\n                page-break-after: avoid\n            }\n\n            #toc, .sidebarblock, .exampleblock > .content {\n                background: none !important\n            }\n\n            #toc {\n                border-bottom: 1px solid #dddddf !important;\n                padding-bottom: 0 !important\n            }\n\n            body.book #header {\n                text-align: center\n            }\n\n            body.book #header > h1:first-child {\n                border: 0 !important;\n                margin: 2.5em 0 1em\n            }\n\n            body.book #header .details {\n                border: 0 !important;\n                display: block;\n                padding: 0 !important\n            }\n\n            body.book #header .details span:first-child {\n                margin-left: 0 !important\n            }\n\n            body.book #header .details br {\n                display: block\n            }\n\n            body.book #header .details br + span::before {\n                content: none !important\n            }\n\n            body.book #toc {\n                border: 0 !important;\n                text-align: left !important;\n                padding: 0 !important;\n                margin: 0 !important\n            }\n\n            body.book #toc, body.book #preamble, body.book h1.sect0, body.book .sect1 > h2 {\n                page-break-before: always\n            }\n\n            .listingblock code[data-lang]::before {\n                display: block\n            }\n\n            #footer {\n                padding: 0 .9375em\n            }\n\n            .hide-on-print {\n                display: none !important\n            }\n\n            .print-only {\n                display: block !important\n            }\n\n            .hide-for-print {\n                display: none !important\n            }\n\n            .show-for-print {\n                display: inherit !important\n            }\n        }\n\n        @media print, amzn-kf8 {\n            #header > h1:first-child {\n                margin-top: 1.25rem\n            }\n\n            .sect1 {\n                padding: 0 !important\n            }\n\n            .sect1 + .sect1 {\n                border: 0\n            }\n\n            #footer {\n                background: none\n            }\n\n            #footer-text {\n                color: rgba(0, 0, 0, .6);\n                font-size: .9em\n            }\n        }\n\n        @media amzn-kf8 {\n            #header, #content, #footnotes, #footer {\n                padding: 0\n            }\n        }\n    </style>\n</head>\n<body class=\"article\">\n<div id=\"header\">\n</div>\n<div id=\"content\">\n    <div class=\"sect1\">\n        <h2 id=\"_intellij_idea最佳实践\">IntelliJ IDEA最佳实践</h2>\n        <div class=\"sectionbody\">\n            <div class=\"olist arabic\">\n                <ol class=\"arabic\">\n                    <li>\n                        <p>Intellij IDEA for Java WEB 开发</p>\n                        <div class=\"ulist\">\n                            <ul>\n                                <li>\n                                    <p>快捷键</p>\n                                </li>\n                                <li>\n                                    <p>插件</p>\n                                </li>\n                                <li>\n                                    <p>快速测试</p>\n                                </li>\n                                <li>\n                                    <p>Java工具包</p>\n                                </li>\n                            </ul>\n                        </div>\n                    </li>\n                    <li>\n                        <p>Intellij IDEA for Scala 开发(ing)</p>\n                    </li>\n                    <li>\n                        <p>Intellij IDEA for Kotlin 开发(ing)</p>\n                    </li>\n                </ol>\n            </div>\n            <div class=\"admonitionblock note\">\n                <table>\n                    <tr>\n                        <td class=\"icon\">\n                            <div class=\"title\">Note</div>\n                        </td>\n                        <td class=\"content\">\n                            如无特殊说明, 本文基于Mac OS 及Intellij IDEA 2020.1.x,<br>\n                            涉及系统或版本差异时会就近补充说明,<br>\n                            总体上: Mac的<strong>\n                            <mark>cmd</mark>\n                        </strong>等价于Windows的<strong>\n                            <mark>ctrl</mark>\n                        </strong>,<br>\n                            Intellij IDEA高版本功能是兼容低版本功能的, 只是部分插件会受到一些影响\n                        </td>\n                    </tr>\n                </table>\n            </div>\n            <div class=\"sect2\">\n                <h3 id=\"_快捷键\">快捷键</h3>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p>找到所有快捷键, <code>Help</code> -&#8594; <code>Keymap Reference</code>, 出现的PDF展示了当前你的编辑器的所有快捷键</p>\n                        </li>\n                        <li>\n                            <p>确实有点多, 不着急, 知道了方法, 后续只是时间问题.\n                                如何搜索快捷键, 参见下图</p>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"Shortcut\" src=\"http://file.debuggerpowerzcy.top/power/Shortcut.png\">\n                    </div>\n                    <div class=\"title\">Figure 1. 如何搜索快捷键</div>\n                </div>\n                <table class=\"tableblock frame-all grid-all stretch\">\n                    <caption class=\"title\">Table 1. 10个高频快捷键</caption>\n                    <colgroup>\n                        <col style=\"width: 33.3333%;\">\n                        <col style=\"width: 33.3333%;\">\n                        <col style=\"width: 33.3334%;\">\n                    </colgroup>\n                    <thead>\n                    <tr>\n                        <th class=\"tableblock halign-left valign-top\">功能</th>\n                        <th class=\"tableblock halign-left valign-top\">关键词</th>\n                        <th class=\"tableblock halign-left valign-top\">示例(默认)快捷键</th>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">①语句自动完成</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Complete statement</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">cmd + shift + enter</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">②复写(父类)方法</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Override methods | Generate</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">ctrl + O | ctrl + enter</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">③智能提示|纠错</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Show Context Actions</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">ctrl + shift + alt + enter</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">④快速复制粘贴</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Duplicate Line or Selection</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">cmd + D</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑤查看方法调用</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Call Hierarchy</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">ctrl + alt + H</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑥跳转到父类申明</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Go to Super Method</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">cmd + U</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑦跳转到子类实现</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Go to Declaration or Usages</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">cmd + B</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑧拼接下一行</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Join Lines</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">ctrl + shift + J</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑨优化导包</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Optimize Imports</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">ctrl + alt + O</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">⑩格式化代码</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">Reformat Code</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">cmd + alt + L</p></td>\n                    </tr>\n                    <tr>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">更多彩蛋</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">安装插件 Key Promoter X</p></td>\n                        <td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\">对于有快捷键的按钮, 当你点击时提示告诉你快捷键</p></td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n            <div class=\"sect2\">\n                <h3 id=\"_插件\">插件</h3>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/9792-key-promoter-x/\">Key Promoter X</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>快捷键提示, 新手必备, 而老手也可以通过它得知新版IDEA的一些特性信息</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/10080-rainbow-brackets/\">Rainbow Brackets</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>代码括号自动匹配, 彩板护眼</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/6317-lombok/\">Lombok</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>这位都听说过吧, 没听过的要么是大佬要么改行吧</p>\n                                    </li>\n                                    <li>\n                                        <p>采坑经验, 使用Lombok时, 尽量避免对象间继承, 如果非要继承, 应考虑@EqualsAndHashCode(callSuper = true : false)</p>\n                                    </li>\n                                    <li>\n                                        <p>示例:</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"listingblock\">\n                    <div class=\"content\">\n<pre class=\"CodeRay highlight\"><code data-lang=\"jave\">/**\n * balabala\n *\n * @author Mr.X\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\n@EqualsAndHashCode(callSuper = true)\npublic class PormHub extends GitHub{\n    private Boolean well = Boolean.FALSE;\n}</code></pre>\n                    </div>\n                </div>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/7391-asciidoc/\">AsciiDoc</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>文档编辑神器, AsciiDoc本身目标是制作大型电子书, 超越MarkDown, 本文就是用AsciiDoc书写完成的</p>\n                                    </li>\n                                    <li>\n                                        <p><strong>Spring</strong>官方、<strong>Spring-Alibaba</strong>官方都采用AsciiDoc撰写文档, <strong>GitHub</strong>也支持AsciiDoc, AsciiDoc是未来的主流, MarkDown貌似要成替补了</p>\n                                    </li>\n                                    <li>\n                                        <p>个人使用体验, 对于写技术文档, 上手快, 简洁, 本文的一个小目标就是为新手提供常用的模块, 支持ctrl + c | v</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"AsciiDoc\" src=\"http://file.debuggerpowerzcy.top/power/AsciiDoc.png\">\n                    </div>\n                    <div class=\"title\">Figure 2. AsciiDoc文档速览</div>\n                </div>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/8579-translation/\">Translation</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>作为中国程序员, 英语不会咋办?</p>\n                                    </li>\n                                    <li>\n                                        <p>安装该插件, 选中任意文本, <strong>ctrl + alt + T</strong> 一键翻译</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/6725-ibatis-mybatis-mini-plugin/\">iBATIS/MyBatis mini-plugin</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>对于采用Mybatis且保留SQL的方式, 从Mapper接口跳转到对应SQL处, 可以借助该插件完成</p>\n                                    </li>\n                                    <li>\n                                        <p>当然现在有很多采用无SQL的方式, 参见 <a href=\"https://github.com/baomidou/mybatis-plus\">苞米豆</a></p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/7179-maven-helper/\">MavenHelper</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>国内Java工程多采用Maven来管理依赖, 对于一些不讲究的老项目, 依赖纠缠不清, 这个时候咋办?</p>\n                                    </li>\n                                    <li>\n                                        <p>就这样, 凉拌吧!</p>\n                                    </li>\n                                    <li>\n                                        <p>又或者, MavenHelper带你浴火重生, 请看下图</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"MavenHelper\" src=\"http://file.debuggerpowerzcy.top/power/MavenHelper.png\">\n                    </div>\n                    <div class=\"title\">Figure 3. MavenHelper特性速览</div>\n                </div>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/8286-sequencediagram/\">SequenceDiagram</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>当我们跳槽后接坑时, 代码的链路是怎样的, 怎么没完没了呢?</p>\n                                    </li>\n                                    <li>\n                                        <p>这个时候, SequenceDiagram带你一览全貌</p>\n                                    </li>\n                                    <li>\n                                        <p>方法调用时序图出来了, 慢慢瞅吧!</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"SequenceDiagram\" src=\"http://file.debuggerpowerzcy.top/power/SequenceDiagram.png\">\n                    </div>\n                    <div class=\"title\">Figure 4. SequenceDiagram特性速览</div>\n                </div>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p><a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode/\">D8gerAutoCode</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>作为Web开发, 当业务理解清楚后, 开发过程就可以量化如下:</p>\n                                        <div class=\"olist arabic\">\n                                            <ol class=\"arabic\">\n                                                <li>\n                                                    <p>表设计</p>\n                                                </li>\n                                                <li>\n                                                    <p>SQL &#8594; Mapper &#8594; Mo &#8594; &#8594; handler &#8594; <strong>Service</strong> &#8594; Controller</p>\n                                                </li>\n                                                <li>\n                                                    <p>自测</p>\n                                                </li>\n                                                <li>\n                                                    <p>联调</p>\n                                                </li>\n                                                <li>\n                                                    <p>PM加需求, 再改一波&#8230;&#8203;</p>\n                                                </li>\n                                            </ol>\n                                        </div>\n                                    </li>\n                                    <li>\n                                        <p>在上诉步骤中, 我认为1、2、3步是自己可以控制的, 且步骤2中除了<strong>Service</strong>层代码由业务决定外, 其他基本代码基本如出一辙</p>\n                                    </li>\n                                    <li>\n                                        <p>这意味着什么?</p>\n                                    </li>\n                                    <li>\n                                        <p>据我的观察, 1-3年的大部分程序员就在写这些重复代码, 有时写错或者抄错了, 到调试时定位到问题, 真的浪费不少时间&#8230;&#8203;</p>\n                                    </li>\n                                    <li>\n                                        <p>好在不少前辈通过创建工具, 以逆向工程方式生成<code><strong>生产环境可用的</strong></code>基础代码, 操作嘛也比较简单, 定义好SQL, 编写配置文件然后运行main方法生成</p>\n                                    </li>\n                                    <li>\n                                        <p>我的编码生涯里也有不少这样的回忆, 只是里面仍旧有不少重复操作, 甚至多人操作时会产生冲突</p>\n                                    </li>\n                                    <li>\n                                        <p>于是, 我从Mo出发, 写了D8gerAutoCode这个插件, 一切以表设计为核心, 你专注设计好Mo就可以, 其他基本代码使用快捷键一键搞定</p>\n                                    </li>\n                                    <li>\n                                        <p>如果D8gerAutoCode只有这个功能, 那其实和其他大佬插件相比没有啥可比性, 大家都用习惯了, 为何要使用新的呢?</p>\n                                    </li>\n                                    <li>\n                                        <p>重点来了: D8gerAutoCode插件专注<strong><code>解决重复</code></strong>, 在平常工作中的重复工作应该被简化, 在我看来, 程序的初衷不就是如此吗?</p>\n                                    </li>\n                                    <li>\n                                        <p>所以, D8gerAutoCode插件还带有字符串批处理, JSON处理, MySQL处理, 字段命名处理, 针对SwaggerAPI文档的处理, 这些功能是项目开发中都会用到的, 本着一键搞定原则而开发, 欲知详情参见后文</p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8Config\" src=\"http://file.debuggerpowerzcy.top/power/D8Config.png\">\n                    </div>\n                    <div class=\"title\">Figure 5. 插件配置</div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8Generate\" src=\"http://file.debuggerpowerzcy.top/power/D8Generate.png\">\n                    </div>\n                    <div class=\"title\">Figure 6. 生成代码</div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8String\" src=\"http://file.debuggerpowerzcy.top/power/D8String.png\">\n                    </div>\n                    <div class=\"title\">Figure 7. 字符串批处理</div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8Format\" src=\"http://file.debuggerpowerzcy.top/power/D8Format.png\">\n                    </div>\n                    <div class=\"title\">Figure 8. 格式化</div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8Regrex\" src=\"http://file.debuggerpowerzcy.top/power/D8Regrex.png\">\n                    </div>\n                    <div class=\"title\">Figure 9. 正则彩蛋</div>\n                </div>\n            </div>\n            <div class=\"sect2\">\n                <h3 id=\"_快速测试\">快速测试</h3>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p>基于接口进行Http测试</p>\n                        </li>\n                        <li>\n                            <p>整合Swagger-API, 代码及文档, 且支持文档界面进行调试(ing, 后续补充对应的Java实现代码)</p>\n                        </li>\n                        <li>\n                            <p>项目中涉及登录权限等问题, 在HTTP测试时应尽量模拟全, 为前端联调创造真实环境</p>\n                        </li>\n                        <li>\n                            <p>辅助工具</p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>shell + python脚本</p>\n                                    </li>\n                                    <li>\n                                        <p><a href=\"https://httpie.org/\">httpie</a>, 可视化格式化的HTTP请求调用工具包</p>\n                                    </li>\n                                    <li>\n                                        <p><a href=\"https://github.com/kevinburke/sshpass\">sshpass</a>, 登录服务器自动输入指定密码, 可实现自动登录</p>\n                                    </li>\n                                    <li>\n                                        <p><a href=\"https://github.com/caofanCPU/D8gerConcurrent\">D8gerConcurrent</a>, 支持登陆解析、自动封装Cookie、 <a href=\"http://www.debuggerpowerzcy.top/home/2020/05/15/EasyHttp%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\">接口并发性能测试</a></p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"listingblock\">\n                    <div class=\"content\">\n<pre>function downLoadResponse() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json -d &gt;&gt;~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json -d &gt;&gt;~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n}\n\nfunction downLoadExcel() {\n    echo \"执行命令内容: \\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json -o ${2}\"\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json -o ${2}\n}\n\nfunction show() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} &lt; ~/Desktop/ssoLogin/requestBody.json ${@:2}\n}\n\n# 开发环境机器\nfunction xDev() {\n    # 借助sshpass工具, 将服务器密码保存在文件第一行, 实现自动登录; 且-t 参数支持登录后跳转到指定目录\n    sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt  ssh Mr.X@xxx.xx.xx.${1}  -t  'cd /XXX/logs/; exec $SHELL'\n}\n\n# 将HTPP请求的响应结果存入指定文件中, 示例: https-downLoadResponse https://www.baidu.com/\nalias https-downLoadResponse='downLoadResponse'\n# 在控制台展示完整的HTTP请求过程, 响应打印在控制台, 示例: https-show https://www.baidu.com/\nalias https-show='show'\n# 对于文件下载, 通过输入参数指定下载后的文件名, 示例: https-downLoadExcel https://www.baidu.com/file/123456 D8ger.zip\nalias https-downLoadExcel='downLoadExcel'\n# 对于开发测试环境多服务器, 简化为: xDev 99, 则自动登录xxx.xx.xx。99服务器\nalias 'xDev=xDev'</pre>\n                    </div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"登录获取COOKIE\" src=\"http://file.debuggerpowerzcy.top/power/D8Login.png\" width=\"并写入指定文件\">\n                    </div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"调用HTTP接口进行测试\" src=\"http://file.debuggerpowerzcy.top/power/D8Http.png\">\n                    </div>\n                </div>\n                <div class=\"paragraph\">\n                    <p>IMPORT: 采用这种方法, 可以告别PostMan或PostWoman及其他软件了, 你只需要<strong>Intellij IDEA</strong> + <strong>iterm2</strong>|xshell + <strong>python</strong>环境</p>\n                </div>\n            </div>\n            <div class=\"sect2\">\n                <h3 id=\"_java工具包\">Java工具包</h3>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p>Intellij IDEA代码简化模板, 这个技巧很香的, 比如常见的判断字符串不为空, 我只需要敲下<code><strong>fsnb</strong></code>, 就会得到如下代码</p>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"listingblock\">\n                    <div class=\"content\">\n<pre>if (StringUtils.isNotBlank(光标在这)) {\n\n}\n\n话不多说, 常用模板定义如下:\n/apim : SwaggerModel字段属性模板\n\noin  : 对象为null         ==&gt; Objects.isNull()\nonn  : 对象不为null       ==&gt; Objects.nonNull()\no2e  : 两对象相等          ==&gt; Objects.equals(, )\none  : 两对象不相等        ==&gt; !Objects.equals(, )\nfoin : 判断对象为null      ==&gt; if (Objects.isNull()) {}\nfonn : 判断对象不为null    ==&gt; if (Objects.nonNull()) {}\nfo2e : 判断两对象相等      ==&gt; if (Objects.equals(, )) {}\nfone : 判断两对象不相等    ==&gt; if (!Objects.equals(, )) {}\n\ncie  : 集合为空           ==&gt; CollectionUtil.isEmpty()\ncne  : 集合不为空          ==&gt; CollectionUtil.isNotEmpty()\nsib  : 字符串为空          ==&gt; StringUtils.isBlank()\nsnb  : 字符串不为空        ==&gt; StringUtils.isNotBlank()\nfcie : 判断集合为空        ==&gt; if (CollectionUtil.isEmpty()){}\nfcne : 判断集合不为空      ==&gt; if (CollectionUtil.isNotEmpty()){}\nfsib : 判断字符串为空      ==&gt; if (StringUtils.isBlank()) {}\nfsnb : 判断字符串不为空    ==&gt; if (StringUtils.isNotBlank()) {}</pre>\n                    </div>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"代码模板\" src=\"http://file.debuggerpowerzcy.top/power/D8LiveTemplate.png\">\n                    </div>\n                </div>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p>高频工具包, 推荐GitHub开源项目 <a href=\"https://github.com/caofanCPU/D8gerStarters\">D8gerStarters</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>通用工具包子项目 <a href=\"https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-common-util\"><code><strong>spring-cloud-starter-d8ger-common-util</strong></code></a></p>\n                                        <div class=\"olist arabic\">\n                                            <ol class=\"arabic\">\n                                                <li>\n                                                    <p>集合流式处理工具<strong>CollectionUtil</strong>, 分组、求和、排序应有尽有, 基本可以告别for循环</p>\n                                                </li>\n                                                <li>\n                                                    <p>树形处理工具<strong>WrapTreeUtil</strong>, 列表与树的多种转换骚操作也是应有尽有, 并且具有无侵入性, 开箱即用</p>\n                                                </li>\n                                                <li>\n                                                    <p>数字精度运算工具<strong>NumberUtil</strong>, 金额进度计算, 精准百分比</p>\n                                                </li>\n                                                <li>\n                                                    <p>枚举处理规范<strong>IEnum</strong>, 为项目打好根基, 规范枚举值用</p>\n                                                </li>\n                                            </ol>\n                                        </div>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p>中间件可插拔Starters整合工具包, 推荐GitHub开源项目 <a href=\"https://github.com/caofanCPU/D8gerStarters\">D8gerStarters</a></p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>通用工具包子项目 <a href=\"https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-web-util\"><code><strong>spring-cloud-starter-d8ger-web-util</strong></code></a></p>\n                                        <div class=\"olist arabic\">\n                                            <ol class=\"arabic\">\n                                                <li>\n                                                    <p>整合常用中间件, 例如业务线程池、邮件、Redis缓存、RestTemplate调用、消息队列、接口响应消息转换器、SwaggerAPI文档处理器</p>\n                                                </li>\n                                                <li>\n                                                    <p>开关型可插拔, 默认有一套经过大型生产环境检验过的配置, 支持通过配置文件更改配置</p>\n                                                </li>\n                                                <li>\n                                                    <p>保留扩展点, 通过继承等方式覆盖原有组件</p>\n                                                </li>\n                                            </ol>\n                                        </div>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"sect2\">\n                <h3 id=\"_总结\">总结</h3>\n                <div class=\"ulist\">\n                    <ul>\n                        <li>\n                            <p>3个开源项目相辅相成, 目的与Spring等框架一致, 解决&#8217;最后一站&#8217;的重复问题, 以工具的使命提高编码效率, 让我们专注于业务开发</p>\n                            <div class=\"ulist\">\n                                <ul>\n                                    <li>\n                                        <p>Intelli IDEA智能生码插件, <a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode/\">D8gerAutoCode</a></p>\n                                    </li>\n                                    <li>\n                                        <p>Python脚本, 解决服务器、登录以及HTTP接口测试里的重复工作, <a href=\"https://github.com/caofanCPU/D8gerConcurrent\">D8gerConcurrent</a></p>\n                                    </li>\n                                    <li>\n                                        <p>Java开发者的福利, 炒鸡香的工具集, <a href=\"https://github.com/caofanCPU/D8gerStarters\">D8gerStarters</a></p>\n                                    </li>\n                                </ul>\n                            </div>\n                        </li>\n                        <li>\n                            <p><strong>捐赠|Donate</strong>, <strong>实践撰文分享</strong>实属不易, 您的支持能为更多省时省事的分享提速, 如果💰不行, 那就帮上面的开源项目点量⭐吧, 谢谢!</p>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"imageblock\">\n                    <div class=\"content\">\n                        <img alt=\"D8WZ\" src=\"http://file.debuggerpowerzcy.top/power/D8WZ.png\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<div id=\"footer\">\n    <div id=\"footer-text\">\n        Last updated 2020-08-30 00:02:13 +0800\n    </div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "LICENCE",
    "content": "Apache License\nVersion 2.0, January 2019\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n    \"License\" shall mean the terms and conditions for use, reproduction, and\n    distribution as defined by Sections 1 through 9 of this document.\n\n    \"Licensor\" shall mean the copyright owner or entity authorized by the\n    copyright owner that is granting the License.\n\n    \"Legal Entity\" shall mean the union of the acting entity and all other\n    entities that control, are controlled by, or are under common control with\n    that entity. For the purposes of this definition, \"control\" means (i) the\n    power, direct or indirect, to cause the direction or management of such\n    entity, whether by contract or otherwise, or (ii) ownership of\n    fifty percent (50%) or more of the outstanding shares, or (iii) beneficial\n    ownership of such entity.\n\n    \"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\n    permissions granted by this License.\n\n    \"Source\" form shall mean the preferred form for making modifications,\n    including but not limited to software source code, documentation source,\n    and configuration files.\n\n    \"Object\" form shall mean any form resulting from mechanical transformation\n    or translation of a Source form, including but not limited to compiled\n    object code, generated documentation, and conversions to\n    other media types.\n\n    \"Work\" shall mean the work of authorship, whether in Source or Object\n    form, made available under the License, as indicated by a copyright notice\n    that is included in or attached to the work (an example is provided in the\n    Appendix below).\n\n    \"Derivative Works\" shall mean any work, whether in Source or Object form,\n    that is based on (or derived from) the Work and for which the editorial\n    revisions, annotations, elaborations, or other modifications represent,\n    as a whole, an original work of authorship. For the purposes of this\n    License, Derivative Works shall not include works that remain separable\n    from, or merely link (or bind by name) to the interfaces of, the Work and\n    Derivative Works thereof.\n\n    \"Contribution\" shall mean any work of authorship, including the original\n    version of the Work and any modifications or additions to that Work or\n    Derivative Works thereof, that is intentionally submitted to Licensor for\n    inclusion in the Work by the copyright owner or by an individual or\n    Legal Entity authorized to submit on behalf of the copyright owner.\n    For the purposes of this definition, \"submitted\" means any form of\n    electronic, verbal, or written communication sent to the Licensor or its\n    representatives, including but not limited to communication on electronic\n    mailing lists, source code control systems, and issue tracking systems\n    that are managed by, or on behalf of, the Licensor for the purpose of\n    discussing and improving the Work, but excluding communication that is\n    conspicuously marked or otherwise designated in writing by the copyright\n    owner as \"Not a Contribution.\"\n\n    \"Contributor\" shall mean Licensor and any individual or Legal Entity on\n    behalf of whom a Contribution has been received by Licensor and\n    subsequently incorporated within the Work.\n\n2. Grant of Copyright License.\n\n    Subject to the terms and conditions of this License, each Contributor\n    hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,\n    royalty-free, irrevocable copyright license to reproduce, prepare\n    Derivative Works of, publicly display, publicly perform, sublicense,\n    and distribute the Work and such Derivative Works in\n    Source or Object form.\n\n3. Grant of Patent License.\n\n    Subject to the terms and conditions of this License, each Contributor\n    hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,\n    royalty-free, irrevocable (except as stated in this section) patent\n    license to make, have made, use, offer to sell, sell, import, and\n    otherwise transfer the Work, where such license applies only to those\n    patent claims licensable by such Contributor that are necessarily\n    infringed by their Contribution(s) alone or by combination of their\n    Contribution(s) with the Work to which such Contribution(s) was submitted.\n    If You institute patent litigation against any entity (including a\n    cross-claim or counterclaim in a lawsuit) alleging that the Work or a\n    Contribution incorporated within the Work constitutes direct or\n    contributory patent infringement, then any patent licenses granted to\n    You under this License for that Work shall terminate as of the date such\n    litigation is filed.\n\n4. Redistribution.\n\n    You may reproduce and distribute copies of the Work or Derivative Works\n    thereof in any medium, with or without modifications, and in Source or\n    Object form, provided that You meet the following conditions:\n\n    1. You must give any other recipients of the Work or Derivative Works a\n    copy of this License; and\n\n    2. You must cause any modified files to carry prominent notices stating\n    that You changed the files; and\n\n    3. You must retain, in the Source form of any Derivative Works that You\n    distribute, all copyright, patent, trademark, and attribution notices from\n    the Source form of the Work, excluding those notices that do not pertain\n    to any part of the Derivative Works; and\n\n    4. If the Work includes a \"NOTICE\" text file as part of its distribution,\n    then any Derivative Works that You distribute must include a readable copy\n    of the attribution notices contained within such NOTICE file, excluding\n    those notices that do not pertain to any part of the Derivative Works,\n    in at least one of the following places: within a NOTICE text file\n    distributed as part of the Derivative Works; within the Source form or\n    documentation, if provided along with the Derivative Works; or, within a\n    display generated by the Derivative Works, if and wherever such\n    third-party notices normally appear. The contents of the NOTICE file are\n    for informational purposes only and do not modify the License.\n    You may add Your own attribution notices within Derivative Works that You\n    distribute, alongside or as an addendum to the NOTICE text from the Work,\n    provided that such additional attribution notices cannot be construed\n    as modifying the License.\n\n    You may add Your own copyright statement to Your modifications and may\n    provide additional or different license terms and conditions for use,\n    reproduction, or distribution of Your modifications, or for any such\n    Derivative Works as a whole, provided Your use, reproduction, and\n    distribution of the Work otherwise complies with the conditions\n    stated in this License.\n\n5. Submission of Contributions.\n\n    Unless You explicitly state otherwise, any Contribution intentionally\n    submitted for inclusion in the Work by You to the Licensor shall be under\n    the terms and conditions of this License, without any additional\n    terms or conditions. Notwithstanding the above, nothing herein shall\n    supersede or modify the terms of any separate license agreement you may\n    have executed with Licensor regarding such Contributions.\n\n6. Trademarks.\n\n    This License does not grant permission to use the trade names, trademarks,\n    service marks, or product names of the Licensor, except as required for\n    reasonable and customary use in describing the origin of the Work and\n    reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\n    Unless required by applicable law or agreed to in writing, Licensor\n    provides the Work (and each Contributor provides its Contributions)\n    on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n    either express or implied, including, without limitation, any warranties\n    or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS\n    FOR A PARTICULAR PURPOSE. You are solely responsible for determining the\n    appropriateness of using or redistributing the Work and assume any risks\n    associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability.\n\n    In no event and under no legal theory, whether in tort\n    (including negligence), contract, or otherwise, unless required by\n    applicable law (such as deliberate and grossly negligent acts) or agreed\n    to in writing, shall any Contributor be liable to You for damages,\n    including any direct, indirect, special, incidental, or consequential\n    damages of any character arising as a result of this License or out of\n    the use or inability to use the Work (including but not limited to damages\n    for loss of goodwill, work stoppage, computer failure or malfunction,\n    or any and all other commercial damages or losses), even if such\n    Contributor has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\n    While redistributing the Work or Derivative Works thereof, You may choose\n    to offer, and charge a fee for, acceptance of support, warranty,\n    indemnity, or other liability obligations and/or rights consistent with\n    this License. However, in accepting such obligations, You may act only\n    on Your own behalf and on Your sole responsibility, not on behalf of any\n    other Contributor, and only if You agree to indemnify, defend, and hold\n    each Contributor harmless for any liability incurred by, or claims\n    asserted against, such Contributor by reason of your accepting any such\n    warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\n\nCopyright 2019-2025 D8ger/DebuggerKing\n\nLICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE \"LICENSE\");\nYOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE LICENSE.\nYOU MAY OBTAIN A COPY OF THE LICENSE AT\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE\nDISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\nSEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND\nLIMITATIONS UNDER THE LICENSE."
  },
  {
    "path": "README.md",
    "content": "# D8gerAutoCode\n\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode\"><img alt=\"GitHub commit activity\" src=\"https://img.shields.io/github/commit-activity/m/caofanCPU/D8gerAutoCode\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/stargazers\"><img src=\"https://badgen.net/github/stars/caofanCPU/D8gerAutoCode\" alt=\"stars\"></a>\n<a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode\"><img src=\"https://img.shields.io/jetbrains/plugin/d/13576\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode\"><img src=\"https://img.shields.io/github/v/release/caofanCPU/D8gerAutoCode\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/issues\"><img src=\"https://badgen.net/github/open-issues/caofanCPU/D8gerAutoCode\" alt=\"issues\"></a>\n<a href=\"http://file.debuggerpowerzcy.top/power/html/IntelliJBestAction.html\"><img src=\"https://img.shields.io/github/search/caofanCPU/D8gerAutoCode/D8ger\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/pulls\"><img src=\"https://badgen.net/badge/PRs/welcome/cyan\" alt=\"PRs Welcome\"></a>\n<a href=\"https://github.com/D8ger\"><img src=\"https://badgen.net/badge/organization/join%20us/cyan\" alt=\"open-source-organization\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/blob/master/LICENCE\"><img src=\"https://badgen.net/github/license/caofanCPU/D8gerAutoCode?color=green\" alt=\"license\"></a>\n\n[![Stargazers over time](https://starchart.cc/caofanCPU/D8gerAutoCode.svg)](#)\n\n## IDEA Code Automatically Generate Plugin • `For Java Version`  \n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/D8ger-V5.jpg\" /> \n</div>\n\n> [中文说明](./README_CN.md)\n\n## Attention\nThe latest version is **4.1** is approved by the official on 10th, May.  \nIf you can't fetch it, then [click here](https://github.com/caofanCPU/D8gerAutoCode/releases/tag/4.0) to download ~~.zip~~ file.  \nImportant: This version has been implemented [DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8).  \nThat is, some functions have been migrated to another plugin named [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao). After testing, installing two plugins will not affect performance. So, I hope you use happy and give me a 🌟, thx!\n\n### Preface\nAs JetBrains' said, I believe that you should be good use of tools will save you precious hours on your busing work.\n\nI always wonder, \"If someone else has already solved the repeating work, why do I need to repeat it again?\"\n\nWell, that's a valid question for my drive to find the repeat parts at daily work and develop this plugin to save my time.  \n\n### [Quick Start](http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/)\n<a href=\"http://file.debuggerpowerzcy.top/power/html/IntelliJBestAction.html\" target=\"_blank\">ZN程序员福利</a>\n\n### Convention\n- The general problem provides standard solutions\n- The personalized problem only provides example solutions\n\n### Original design intention\n- Remove the fixed duplication coding for improving efficiency in development  \n- Provide available code templates that can be used without modification  \n- Support code directory configuration, only by self-guided package intelligent programming can be done in one-click  \n- Support user-defined configuration, you can specify which file to be generated  \n\n### Features\n\n- ~~Camel-Underline-Uppercase-Uncapitalize-Lowercase can be converted to each other by shortcut~~ `alt` + `shift` + `cmd` + `U`\n- The comments of generated codes support English(Default) | Chinese Simplified(Optional) configuration\n- ~~JSON formatting and single line text conversion, supporting section and whole document, default shortcut~~ `alt`+`shift`+`cmd`+`J` | `S`\n- Generating `data table definition SQL` | `Mo` | `Mapper` | `Handler`, single table addition, deletion, modification and search with paging in one click\n- Under the help of SwaggerApi generating `Vo` | `Controller` with friendly document description, in addition to this, supporting `Vo` field automatic sorting\n- For smart coding, you just need one shortcut default as `alt`+`shift`+`cmd`+`D`\n- Supporting customer configuration, for example, specify the author who you are\n- Reserve easter eggs, you can try to edit the blank file in IDEA and type `d8ger` to get the default configuration template\n- ~~Reserve easter eggs, edit the blank file in IDEA and enter `nasa` to get the NASA configuration file template. This is very useful and efficient for handling multi-lines, especially SQL field naming processing.~~\n- ~~Reserve easter eggs, edit the blank file in IDEA and enter `regex` to get some commonly used regular expressions. Other code Easter eggs will be added later.~~\n- For automatic sorting `Vo` field , you just need one shortcut default as `alt`+`shift`+`cmd`+`O`\n\n### Using manual(v3.0+)\n1.Open the configuration box to set the generation parameters, `Preference` --> `Other Settings` --> `D8gerAutoCode`\n\n2.Check the file to be generated and choose the generation path, rewrite `author`、`apiUrlPrefix` and `locale`, and click the button to save your configuration.  \n\n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/D8King.jpg\" /> \n</div>\n\n### Using manual(under v3.0)\n1. Create Model Class\n\n2. Select the class name and press the (default) shortcut `alt`+`shift`+`cmd`+`D`\n\n3. Under the default configuration, `D8gerAutoCode` directory and `data table SQL definitions` and **Web codes** will be generated\n\n4. So, What you need to do:\n    - Under a multi-module project, configure the generated file output directory, for example, **`Mo.java`** should be moved into the `model` directory  \n    - Add non-null constraints to **`xx.sql`** as required  \n    - If you generated the **Controller.java** file, please note the interface returns type of **`Object`**, it should be modified to the project's uniform return type  \n    - In the above steps the `xx.java` file will report some errors, ***don't worry***, these just require you to import packages\n\n5. Default configuration file template for easter egg:\n    - In the ***`resource`*** root directory of the module where the `Model class` is located, create `d8ger.properties` property configuration file\n    - Type `d8ger` and click on `Tools`-> `D8ger`-> `D8gerMore`, and you will find some surprise\n\n6. ~~Regex template for easter egg:~~\n    - ~~Choose any blank file, Type `regex` and click on `Tools`-> `D8ger`-> `D8gerMore`, and you will find some surprise~~\n\n7. ~~NASA template for easter egg:~~\n    - ~~Choose any blank file, Type `nasa` and click on` Tools`-> `D8ger`-> `D8gerMore`, and you will get the NASA manual~~\n    - ~~Follow the manual, custom your config and write your own multi-lines need to be batch handled, then you will find some surprise~~\n\n8. ~~Camel-Underline-Uppercase-Uncapitalize-Lowercase circle convert by one-click~~\n    - ~~Choose word text in any editing file, press `alt` + `shift` + `cmd` + `U`, you`ll find the changed word~~\n    - ~~If not satisfied just press the shortcut again and again util you are.~~\n\n9. You will get the following default configuration information\n    - It's recommended that you change the configuration items\n        - `author` (you can't sign my name for the pits you dug!)\n        - `apiUrlPrefix` (the interface url prefix should be configured as the project interface unified URL prefix)\n        - generate file output directory under a multi-module project\n    - As for `boolean` configuration items, let you choose which files need to be generated, and specify output directory is optional\n\n> By the way, these default shortcuts used in Mac OS, if you use Windows just take `cmd` into `ctrl`.\n\n### How to install\n<a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode\" target=\"_blank\">\n    <img src=\"https://cdn.jsdelivr.net/gh/YiiGuxing/TranslationPlugin@master/images/button-install.png\" alt=\"Get from Marketplace\" title=\"Get from Marketplace\">\n</a>\n\n- `Preference` --> `Plugins` --> `Marketplace` --> type `D8` --> install\n- [IDEA official plugin library installation](https://plugins.jetbrains.com/plugin/13576-d8gerautocode)  \n- As for `Source installation` requires you're familiar with Gradle, I will add more details about how to develop a plugin by ***Gradle*** later\n\n### Bug & Question\n- Known issues\n> Modify the `d8ger.properties` file before generating code, the configuration file does not take effect\n\n```\nSolution\n0. If you upgrade version 3.0+, you won`t see it again.\n1. Because the IDEA file uses the VFS mechanism, as a plug-in to use the monitoring file I think it is not cost-effective  \n2. I also found a reason aboub editing .properties file, sometimes it will take one or two minutes to refresh after you finished  \n3. So, press `cmd` + `s` to force refreshing .properties file and you will solve it.\n```\n\n> The icon of plugin shows error like this: red square with a cross\n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/W-D8ger.png\" /> \n</div>\n\n```\nSolution\n1.This issue is caused by Intellij IDEA of new version feature.\n2.Try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*), you'll fix it.\n```\n\n[Other issues, please come to join room](https://github.com/caofanCPU/D8gerAutoCode/issues)\n\n### VersionRoadHistory\n- 4.1\n    - Fix 'D8gerAutoCode' error file path parsing while in WINDOWS system. For more detail, please refer [issue2](https://github.com/caofanCPU/D8gerAutoCode/issues/2)\n\n- 4.0(HIGH.START)\n    - Important note: This time the function is migrated and upgraded, the plug-in has been divided into functions, the purpose is to be full-time and dedicated, and the general functions are sinking to serve more programmers\n        - No.0: Each plug-in is positioned in two aspects, one is efficient coding, and the other is high-quality knowledge links to help users obtain enough useful information to improve their skills\n        - No.1: [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao), **Published**, located JetBrains full product plug-in, General functions, covering text parsing, numerical processing, shell script processing\n        - No.2: [D8gerAutoCode](https://github.com/caofanCPU/D8gerAutoCode), **Published**, located IntelliJ IDEA, auto coding\n        - No.3: D8gerByteSleep, Hatching, located PyCharm\n        - No.4: D8gerJustGo, Hatching, located GoLand\n        - No.5: D8gerAndison, Hatching, located Android Studio\n        - No.6: D8gerWebit, Hatching, located WebStorm\n        - No.7: RoadMap refers [DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8)\n    - Function migration:\n        - BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore are migrated into plugin named [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao)\n        - The shortcut keys and usage methods have not changed, only the code generation functions related to Java are retained\n- 3.4\n    - Addition: 'OhMyZSH' easter eggs, try to type 'ohmyzsh' in the blank file in IDEA to get some useful linux commands. I'm sure you'll save much time.\n    - BugFix: Fix donate url(I'm waiting for your 🌟 the project on the github).\n    - Optimization: 'BeautifulJSON', 'SimplifyOneLine' and 'BeautifulMySQL' now supports section or whole document convert.\n- 3.2\n    - BugFix: Fix 'BeautifulJSON' issue when parsing complex JSON string.\n    - Optimization: 'CamelUnderlineConvert' now supports Timestamp-LocalDateTime convert, select the text and use origin shortcut `alt` + `shift` + `cmd` + `U` to find out.\n- 3.1\n    - BugFix:\n        - Fix config item `locale` problem when selected as `ZN`, and before the 3.0 version`s comment was English default.\n        - Fix SQL definition in x.sql file ✌️.\n        - Fix batch insert records in xMapper.xml file cause `id`, `createTime`, `updateTime` all should be according to the Database.\n    - Optimization: Config item `autoDetectSQLTimeColumn` now is more intelligent. If you checked, `createTime` and `updateTime` would be generated perfectly in there right position.\n- 3.0\n    - Addition:\n        - Grand celebration for `D8gerAutoCode` getting his face! Now you can config the generated property parameters by setting GUI.\n        - First, Open the configuration box to set the generation parameters, `Preference` --> `Other Settings` --> `D8gerAutoCode`\n        - Then, Check the file to be generated and choose the generation path, rewrite `author`、`apiUrlPrefix` and `locale`, and click the button to save your configuration.\n    - Optimization: Support project level setting parameters for non-invasive, d8ger.properties should exist invisible.\n    - Adjustment: Remove the generated params by `d8ger.properties` file, replace of D8gerAutoCode setting GUI.\n- 2.5\n    - Addition:\n        - Add `autoDetectSQLTimeColumn` configuration for supporting disable default generating `create_time` and `update_time` column definition in SQL.\n        - Add `mapperBatterThenRepository` configuration for supporting custom mapper annotation in both SpringMVC and SpringBoot.\n        - Add `selectOneByExample` in Mapper.java for supporting query one record.\n        - Add `insertSelectiveWithId` in Mapper.java for supporting insert `non null` field and `null` field will be filled with the database default value.\n    - Optimization: 'cause `id` is the primary key, all insert operations should exclude `id` column.\n    - BugFix:\n        - Generation `update_time` column definition remove the rare comma.\n        - Troubleshooting the rare dir named `D8gerAutoCode`, now you can see it only with unspecified directory configuration.\n    - Adjustment: Remove `ServiceInterface` and `ServiceImpl`, 'cause I think `Handler` is more suitable.\n- 2.4\n    - Addition: One-click to beauty MySQL, isn't fragrant?\n    - Optimization: String parsing performance.\n    - Attention: Select your MySQL text, ctrl + alt + shift + `B` will back a surprise.\n- 2.3\n    - BugFix: Json format bug.\n    - Addition:\n        - NASA easter eggs, try to type `nasa` in the blank file in IDEA to get the nasa-template.\n        - NASA easter eggs, multi-lines can be batch handled with the nasa-template, special for sql columns.\n    - Optimization: \n        - Optimize some regex performance.\n        - Support linebreak or comma as the delimiter.\n        - Support windows linebreak when rendering origin code.\n    - Attention: \n        - When execute auto-coding, you should be careful at the linebreak, it maybe different from your project config.\n    - Adjustment: \n        - Icons changed for align, friendly view etc.\n        - The manual of this plugin has been moved to my <a href=\"http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\">website</a>.\n- 2.1\n    - BugFix: add Uncapitalize, and the circle is Camel-Underline-Uppercase-Uncapitalize-Lowercase.\n    - Optimization: Optimize some regex performance.\n    - Attention: Regex easter eggs add some very useful regex search-replace skills hidden in JetBrains's IDE products. Try to learn, and you will save much time at working.\n- 2.0\n    - BugFix: Modify method name in Controller.java.\n    - Addition:\n        - Remove repeat work of moving file into directories for smart coding.\n        - Camel-Underline-Uppercase-Lowercase can be converted to each other by shortcut `alt` + `shift` + `cmd` + `U`.\n        - Regex easter eggs, try to type `regex` in the blank file in IDEA to find it.\n    - Optimization: Optimize source code and improve performance.\n    - Attention: If the icon of plugin shows error(red square with a cross), try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*).\n- 1.24\n    - BugFix: Update method named `updateBatchByPrimaryKeySelective` in mapper.xml.\n    - Addition: Set default language English and you can config it as Chinese Simplified, as before, typing `d8ger` for the latest configuration template.\n    - Attention: You should configure your database connection like `allowMultiQueries=true` for supporting batchUpdate operation.\n- 1.23\n    - BugFix: Fix required dependencies by JetBrains's suggestion for some known compatibility issues.\n    - Addition: Add JSON-formatter and WhiteChar-cleaner.\n    - Attention: Can you 🌟 the project on the github?\n- 1.22\n    - BugFix: Fix README of style, description, picture problems.\n    - Enhance: Enhance profile for generating codes by using regex to replace the circle of matching string.\n    - Attention: Can you 🌟 the project on the github?\n- 1.21\n    - BugFix: Fix README of style, description, picture problems.\n    - Addition: Add MoExample autoCoding for supporting simple sql.\n    - Attention: Can you 🌟 the project on the github?\n- 1.20\n    - Completion: Auto coding for Mo/Example/Mapper/Xml/SQL/Service completed, wow!\n    - Attention: Can you 🌟 the project on the github?\n\n### Contribute\n- Please give me a 🌟\n- Raise demand, write the repetitive problems you often handled at daily work in [issue](https://github.com/caofanCPU/D8gerAutoCode/issues)\n- Invite me to sit at the 🍦 shop\n<table>\n    <tr>\n      <td align=\"center\" style=\"width: 200px;\">\n        <a href=\"https://github.com/D8ger\">\n          <img src=\"http://file.debuggerpowerzcy.top/power/WX.png\" style=\"width: 400px;\"><br>\n          <sub>微信</sub>\n        </a><br>\n      </td>\n      <td align=\"center\" style=\"width: 200px;\">\n        <a href=\"http://www.debuggerpowerzcy.top/\">\n          <img src=\"http://file.debuggerpowerzcy.top/power/ZFB.png\" style=\"width: 400px;\"><br>\n          <sub>支付宝</sub>\n        </a><br>\n      </td>\n      <td align=\"center\" style=\"width: 200px;\">\n          <a href=\"https://github.com/caofanCPU\">\n            <img src=\"http://file.debuggerpowerzcy.top/power/MX.jpg\" style=\"width: 400px;\"><br>\n            <sub>MiXin</sub>\n          </a><br>\n      </td>\n    </tr>\n</table>\n\n### Thanks\n<a href=\"https://www.jetbrains.com/?from=D8gerAutoCode\">\n    <img border=\"0\" src=\"http://file.debuggerpowerzcy.top/power/jetbrains-variant-4.svg\" width=\"131\" alt=\"JetBrains\"><br>\n    <sub>With JetBrains team's open source certificate supporting, this project will continue to develop in the spirit of open source</sub>\n</a>\n"
  },
  {
    "path": "README_CN.md",
    "content": "# D8gerAutoCode\n\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode\"><img alt=\"GitHub commit activity\" src=\"https://img.shields.io/github/commit-activity/m/caofanCPU/D8gerAutoCode\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/stargazers\"><img src=\"https://badgen.net/github/stars/caofanCPU/D8gerAutoCode\" alt=\"stars\"></a>\n<a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode\"><img src=\"https://img.shields.io/jetbrains/plugin/d/13576\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode\"><img src=\"https://img.shields.io/github/v/release/caofanCPU/D8gerAutoCode\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/issues\"><img src=\"https://badgen.net/github/open-issues/caofanCPU/D8gerAutoCode\" alt=\"issues\"></a>\n<a href=\"http://file.debuggerpowerzcy.top/power/html/IntelliJBestAction.html\"><img src=\"https://img.shields.io/github/search/caofanCPU/D8gerAutoCode/D8ger\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/pulls\"><img src=\"https://badgen.net/badge/PRs/welcome/cyan\" alt=\"PRs Welcome\"></a>\n<a href=\"https://github.com/D8ger\"><img src=\"https://badgen.net/badge/organization/join%20us/cyan\" alt=\"open-source-organization\"></a>\n<a href=\"https://github.com/caofanCPU/D8gerAutoCode/blob/master/LICENCE\"><img src=\"https://badgen.net/github/license/caofanCPU/D8gerAutoCode?color=green\" alt=\"license\"></a>\n\n[![Stargazers over time](https://starchart.cc/caofanCPU/D8gerAutoCode.svg)](#)\n\n## IDEA代码自动生成插件•`Java版本`\n\n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/D8ger-V5.jpg\" /> \n</div>\n\n## 说明\n\n最新版本为**4.1**, 在 _**`05月10号`**_ 通过官方审核  \n如果无法获取, [戳此](https://github.com/caofanCPU/D8gerAutoCode/releases/tag/4.1) 下载~~.zip~~压缩包  \n如果用的不错, 给我点个🌟呗, thx!  \n重要: 本版本已执行[DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8).  \n即部分功能已迁入另一个插件[LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao). 经过测试, 安装两个插件一本不会影响性能, 还请小伙伴们支持\n\n### 序言\n\n正如JetBrains所说, 我相信你在繁忙编码工作中时应该善用工具以节省宝贵的时间。\n\n我时常在思考, \"如果其他人已经解决了这些重复工作, 为什么我还需要重复解决?\"\n\n这个问题一直驱动着我, 在日常工作中探寻重复部分并开发此插件以节省时间。\n\n### [快速开始](http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/)\n<a href=\"http://file.debuggerpowerzcy.top/power/html/IntelliJBestAction.html\" target=\"_blank\">ZN程序员福利, IntelliJ IDEA最佳实践</a>\n\n### 约定\n- 通用问题提供规范解法\n- 个性化问题只提供示例解法\n\n### 设计初衷\n- 移除开发中的固定的重复编码过程, 提升开发效率\n- 提供可用的代码模板, 基本不用修改就可使用的代码\n- 支持代码目录配置, 一键自动生成代码, 仅需自行导包即可完成智能编程\n- 支持用户自定义配置, 可指定需要生成的文件\n\n### 功能特性\n\n- ~~驼峰-下划线-大写-首字母小写-小写, 时间戳与标准时间字符串(香!), 一键转换, 默认快捷键~~ `alt` + `shift` + `cmd` + `U`\n- 生成代码的注释支持英语|汉语配置\n- ~~JSON格式化与单行文本转换, 默认快捷键~~ `alt`+`shift`+`cmd`+`J` | `S`\n- 一键生成`数据表定义SQL` | `Mo` | `Mapper` | `Handler`, 单表增删改查+分页一键搞定\n- 结合SwaggerApi, 一键生成带文档定义`Vo`及`Controller`, 支持Vo字段自动排序\n- 一键智能编程, 默认快捷键 `alt`+`shift`+`cmd`+`D`\n- 支持用户自定义配置, 指定生成哪些文件及文件author等\n- 预留彩蛋, 在IDEA中编辑空白文件输入`d8ger`即可得到配置文件模板\n- ~~预留彩蛋, 在IDEA中编辑空白文件输入`nasa`即可得到NASA模板, 针对多行字符串批量处理, 尤其是SQL字段命名处理~~\n- ~~预留彩蛋, 在IDEA中编辑空白文件输入`regex`即可得到一些常用的有趣正则表达式, 后期会增加其他代码彩蛋~~\n- SwaggerVo字段排序, 默认快捷键 `alt`+`shift`+`cmd`+`O`\n\n### 使用手册(v3.0+)\n1.打开配置框设置生成参数 `Preference` --> `Other Settings` --> `D8gerAutoCode`\n\n2.勾选要生成的文件及生成路径, 指明 `author`、`apiUrlPrefix`、`locale`, 保存即可\n\n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/D8King.jpg\" /> \n</div>\n\n### 使用手册(v3.0以下)\n\n1. 创建Model类\n\n2. 选中类名, 按下(默认)快捷键 `alt`+`shift`+`cmd`+`D`\n\n3. 默认配置下, 会生成`D8gerAutoCode`目录及数据表SQL定义和Web代码, 共9个\n\n4. 你需要做的:\n    - 多模块工程下, 配置生成文件输出目录, 例如 **`Mo.java`** 配置`model`目录\n    - 根据需求对 **`xx.sql`** 增加非空约束\n    - 如果你生成了 **`Controller.java`** 文件, ***请注意接口返回对象类型***, 应修改为项目统一的返回类型\n    - 在上述步骤中, 代码文件会飘红报错, 别慌, 这需要你自行导包解决\n\n5. 默认配置文件模板, 代码彩蛋:\n    - 在`Model类`所在模块的 ***`resource`*** 根目录下, 创建`d8ger.properties`属性配置文件\n    - 输入`d8ger`并点击`Tools`-->`D8ger`-->`D8gerMore`\n\n6. ~~正则表达式模板, 代码彩蛋:~~\n    - ~~任意空文本, 输入`regex`并点击`Tools`->`D8ger`->`D8gerMore`, 你会得到一点小惊喜~~\n\n7. ~~NASA模板(多行文本批处理), 代码彩蛋:~~\n    - ~~任意空文本, 输入`nasa`并点击`Tools`->`D8ger`->`D8gerMore`, 你会得到NASA操作手册~~\n    - ~~按照NASA手册提示, 自定义配置并输入需要处理的多行文本, 然后你会得到一点小惊喜~~\n\n8. ~~驼峰-下划线-大写-首字母小写-小写, 一键循环转换~~\n    - ~~选中任意编辑状态下文件里的单词, 按下快捷键`alt` + `shift` + `cmd` + `U`, 你会发现选中单词转换了~~\n    - ~~如果不是你想要的结果那就继续重复按下快捷键, 直到是你想要的为止~~\n\n9. 你就得到如下默认配置信息\n    - 推荐你更改的配置项\n        - `author`(你挖的坑可不许署我的名!)\n        - `apiUrlPrefix`(接口url前缀应配置为项目接口统一Url前缀)\n        - 多模块工程下, 生成文件输出目录\n    - 其他`boolean`配置项, 是让你选择需要生成哪些文件, 可选指定输出目录\n\n>以上默认快捷键针对MacOS系统, 对于Windows用户将`cmd`看做`ctrl`即可\n\n### 如何安装\n<a href=\"https://plugins.jetbrains.com/plugin/13576-d8gerautocode\" target=\"_blank\">\n    <img src=\"https://cdn.jsdelivr.net/gh/YiiGuxing/TranslationPlugin@master/images/button-install.png\" alt=\"Get from Marketplace\" title=\"Get from Marketplace\">\n</a>\n\n- `Preference` --> `Plugins` --> `Marketplace` --> type `D8` --> install\n- [IDEA官方插件库安装](https://plugins.jetbrains.com/plugin/13576-d8gerautocode)\n- 源码安装, 这需要你熟悉Gradle, 后期我会详细补充如何使用Gradle开发一个插件\n\n### Bug&问题\n- 已知问题(最新版本3.0中已修复)\n>修改`d8ger.properties`文件后再生成代码, 配置文件不生效\n\n```\n解决方法\n0.升级到3.0及以上版本, 该问题不复存在\n1.由于IDEA文件采用VFS机制, 作为一个插件去采用监听文件我认为是不合算的\n2.此外, 编辑.properties文件时, 内容变更有时会消耗1-2分钟才会更新生效\n3.所以, 执行快捷键`cmd` + `s`强制刷新.properties文件, 即可解决\n```\n\n> 插件图标显示异常, 图标内只出现相交的红叉\n<div align=\"center\">\n    <img src=\"http://file.debuggerpowerzcy.top/power/W-D8ger.png\" /> \n</div>\n\n```\n1.这是Intelij IDEA新版本特性遗留的兼容性小BUG\n2.升级Intelij IDEA版本, 至少为2019.3.*(2019.2.*及以下都会显示异常)\n```\n\n[其他问题, 欢迎前来查房](https://github.com/caofanCPU/D8gerAutoCode/issues)\n\n### 版本演进历史\n- 4.1\n    - Bug修复: 修复'D8gerAutoCode'在WINDOWS系统中文件路径解析错误的问题, 参见[issue2](https://github.com/caofanCPU/D8gerAutoCode/issues/2)\n- 4.0(HIGH.START)\n    - 重要提示: 本次进行功能迁移升级, 插件已进行功能拆分, 目的是专职专责, 通用功能下沉以服务主流编程语言的程序YUAN\n        - No.0: 每个插件定位两方面, 一是高效编码, 二是高质量的知识链接, 帮助用户获取足够有用的信息, 以提高技能\n        - No.1: [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao), **已发布**, 坐标JetBrains全产品插件, 通用功能, 涵盖文本解析, 数值处理, shell脚本处理\n        - No.2: [D8gerAutoCode](https://github.com/caofanCPU/D8gerAutoCode), **已发布**, 坐标IntelliJ IDEA插件, 智能生码\n        - No.3: D8gerByteSleep, 孵化中, 坐标PyCharm插件\n        - No.4: D8gerJustGo, 孵化中, 坐标GoLand插件\n        - No.5: D8gerAndison, 孵化中, 坐标Android Studio插件\n        - No.6: D8gerWebit, 孵化中, 坐标WebStorm插件\n        - No.7: 插件RoadMap参见[DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8)\n    - 功能迁移:\n        - BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore均迁移至插件[LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao)\n        - 快捷键及使用方法均未改变, 仅保留与Java相关的生码功能\n- 3.6\n    - 体验优化: 修改插件LOGO\n- 3.4\n    - 新增功能: 'OhMyZSH' 彩蛋, 空白文件中输入 'ohmyzsh' 将获得一些有用的linux命令工具及使用技巧. 这将节省你不少时间.\n    - Bug修复: 修复donate链接(铁子, 等着你🌟该项目, thx!).\n    - 体验优化: 'BeautifulJSON', 'SimplifyOneLine' 和 'BeautifulMySQL' 现在同时支持部分和整个文件内容转换.\n- 3.2\n    - Bug修复: 修复'BeautifulJSON'在解析复杂JSON字符串时的问题\n    - 体验优化: 'CamelUnderlineConvert' 支持时间戳与标准时间字符串相互转换\n- 3.1\n    - Bug修复:\n        - 修复配置项`locale`为中文时不生效的问题, 在之前的3.0版本只能生成英文注释.\n        - 修复x.sql中在某些情况下因缺失`,`导致报错的问题.\n        - 批量插入记录, 字段`id`, `createTime`, `updateTime`将被忽略强制采用数据库的默认值.\n    - 体验优化: 配置项`autoDetectSQLTimeColumn`现在更加智能. 当你勾选改配置项时, `createTime` and `updateTime`字段将会自动填充到合适的位置.\n- 3.0\n    - 新增功能:\n        - 很高兴宣布插件`D8gerAutoCode`终于有脸(面)了! 现在你将通过设置界面配置生码参数.\n        - 第一步, 打开设置界面, `Preference` --> `Other Settings` --> `D8gerAutoCode`\n        - 第二步, 勾选你要生成的文件并指明文件生成后所在目录, 填写`author`、`apiUrlPrefix` and `locale`, 保存就完事了.\n    - 体验优化: 使用项目级别的界面配置, 对用户的代码无任何侵入性.\n    - 功能调整: 移除`d8ger.properties`配置文件, 一键生码配置参数将通过D8gerAutoCode设置GUI完成.\n- 2.5\n    - 新增功能:\n        - 新增配置项`autoDetectSQLTimeColumn`用以支持`create_time`和`update_time`字段的自动探测定义.\n        - 新增配置项`mapperBatterThenRepository`用以支持`SpringMVC`和`SpringBoot`下的`mapper`注解.\n        - 在Mapper.java文件中新增`selectOneByExample`方法用以支持根据条件查询单条记录, 慢走不送: `xList.get(0)`.\n        - 在Mapper.java文件中新增`insertSelectiveWithId`用以支持只插入非NULL字段, NULL字段将采用数据库默认值.\n    - 体验优化: 考虑到`id`是约定的主键字段, 所有插入操作都应该排除该字段.\n    - Bug修复:\n        - 在x.sql文件定义中, `update_time`在某些情况下会出现多余的`,`.\n        - 颇费周折地抓获冗余目录`D8gerAutoCode`莫名出现的现场, 现在只有在你未指明生成目录的情况下才能遇到他, 版本不停步, 且用且珍惜.\n    - 功能调整: 去除`ServiceInterface`和`ServiceImpl`, 因为针对自动生码的通用性而言`Handler`将更合适.\n- 2.4\n    - 新增功能: 一键美化SQL, 不香吗?\n    - 体验优化: 优化字符串解析性能.\n    - TheShy提示: 选中MySQL文本, 快捷键ctrl + alt + shift + `B`将奉上惊喜.\n- 2.3\n    - Bug修复: Json字符串格式化的问题.\n    - 新增功能:\n        - NASA彩蛋, 空白文件中输入`nasa`获取模板.\n        - NASA彩蛋, 支持字符串批处理, 例如多行文本对齐, 提供SQL格式化及自动生成别名功能, 搞数据分析的小伙伴值得一试.\n    - 体验优化:\n        - 优化正则处理性能.\n        - 支持换行符作为分割符.\n        - 针对Windows系统, 字符串批处理结果渲染时使用Windows换行符.\n    - TheShy提示:\n        - 运行自动生码前, 请留意IDE项目默认换行符配置.\n    - 功能调整:\n        - 插件功能图标调整对齐.\n        - 插件使用指南搬迁到我的<a href=\"http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\">博客</a>.\n- 2.1\n    - Bug修复: 补充一键首字母小写转换功能, 完成字段命名闭环: 驼峰-下划线-全大写-首字母小写-全小写.\n    - 体验优化: 优化一些正则处理的性能.\n    - TheShy提示: 正则神器彩蛋中增加IDEA自带的高效查找与替换功能, 花点时间瞄一瞄, 之后工作快到飞起.\n- 2.0\n    - Bug修复: 修改Controller.java文件中方法名.\n    - 新增功能:\n        - 通过配置指定文件生成目录, 不用再手动拖入目录了, 就应该是这样的, 重复工作应该被剔除.\n        - 驼峰-下划线-大写-小写一键转化: `alt` + `shift` + `cmd` + `U`.\n        - 空白文件中输入`regex` 获取正则神器菜单.\n    - 体验优化: 代码优化与性能优化.\n    - TheShy提示: 如果插件图标出现红叉, 这是IDEA版本不兼容引起的, 将IDEA版本升级至2019.3.*(至少是2019.2.*以后).\n- 1.24\n    - Bug修复: mapper.xml文件中 `updateBatchByPrimaryKeySelective` SQL生成修复.\n    - 新增功能: 空白文件中输入`d8ger`以获取最新模板参数配置, 该版本支持代码注释中英文, 默认英文.\n    - TheShy提示: **对于批量更新功能, 数据库连接参数必须开启该功能: `allowMultiQueries=true`**.\n- 1.23\n    - Bug修复: 修复Intellij版本间的依赖包兼容问题.\n    - 新增功能: 新增一键JSON美化和一键剔除空白字符.\n    - TheShy提示: 老铁, 点亮一颗🌟可好?\n- 1.22\n    - Bug修复: 修正图片及文档格式.\n    - 体验优化: 使用正则匹配取缔原有循环处理以提升性能\n    - TheShy提示: 小伙伴, 点亮一颗🌟可好?\n- 1.21\n    - Bug修复: 修正图片及文档格式.\n    - 新增功能: 新增MoExample查询条件对象以支持简单查询.\n    - TheShy提示: 同学, 点亮一颗🌟可好?\n- 1.20\n    - 首发上阵: 一键自动生成Mo/Example/Mapper/Xml/SQL/Service 完成, wow!\n    - TheShy提示: 少年, 点亮一颗🌟可好?\n\n### 参与贡献\n- 帮我点亮一颗🌟\n- 提需求, 在[issue](https://github.com/caofanCPU/D8gerAutoCode/issues)描述工作中经常处理的重复问题\n- 请我到🍦店坐坐\n<table>\n    <tr>\n      <td align=\"center\" style=\"width: 200px;\">\n        <a href=\"https://github.com/D8ger\">\n          <img src=\"http://file.debuggerpowerzcy.top/power/WX.png\" style=\"width: 400px;\"><br>\n          <sub>微信</sub>\n        </a><br>\n      </td>\n      <td align=\"center\" style=\"width: 200px;\">\n        <a href=\"http://www.debuggerpowerzcy.top/\">\n          <img src=\"http://file.debuggerpowerzcy.top/power/ZFB.png\" style=\"width: 400px;\"><br>\n          <sub>支付宝</sub>\n        </a><br>\n      </td>\n      <td align=\"center\" style=\"width: 200px;\">\n          <a href=\"https://github.com/caofanCPU\">\n            <img src=\"http://file.debuggerpowerzcy.top/power/MX.jpg\" style=\"width: 400px;\"><br>\n            <sub>MiXin</sub>\n          </a><br>\n      </td>\n    </tr>\n</table>\n\n### 致谢\n\n<a href=\"https://www.jetbrains.com/?from=D8gerAutoCode\">\n    <img border=\"0\" src=\"http://file.debuggerpowerzcy.top/power/jetbrains-variant-4.svg\" width=\"131\" alt=\"JetBrains\"><br>\n    <sub>感谢JetBrains团队的开源证书支持, 本项目将秉承开源精神持续开发</sub>\n</a>\n"
  },
  {
    "path": "build.gradle",
    "content": "plugins {\n    id 'java'\n    id 'org.jetbrains.intellij' version '0.4.21'\n}\n\ngroup 'com.xyz.caofancpu'\nversion '4.1'\n\nsourceCompatibility = 1.8\n\nrepositories {\n    mavenCentral()\n    maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' }\n    maven { url 'https://repo1.maven.org/maven2/' }\n}\n\ntasks.withType(JavaCompile) {\n    options.encoding = \"UTF-8\"\n}\n\napply plugin: 'idea'\napply plugin: 'org.jetbrains.intellij'\napply plugin: 'java'\n\n//task myRun(type: JavaExec) {\n//    classpath sourceSets.main.runtimeClasspath\n//    main = \"com.xyz.caofancpu.d8ger.action.D8gerSetting\"\n//}\n\n// 自定义task跑代码\ntask D8ENV {\n    println('帝八哥正在编译插件....')\n//    println \"$System.env.IDEA_HOME\"\n    println(\"IDEA安装环境目录: \" + System.getenv(\"IDEA_HOME\"))\n    println(\"更新IDEA后, 别忘修改变量\\$IDEA_HOME\")\n}\n\ndependencies {\n    testCompile group: 'junit', name: 'junit', version: '4.12'\n    annotationProcessor 'org.projectlombok:lombok:1.18.10'\n    compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.10'\n    compile group: 'commons-io', name: 'commons-io', version: '1.3.2'\n    compile group: 'commons-collections', name: 'commons-collections', version: '3.2.2'\n    compile group: 'ru.lanwen.verbalregex', name: 'java-verbal-expressions', version: '1.8'\n    compile group: 'com.alibaba', name: 'druid', version: '0.2.9'\n    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'\n    compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'\n}\n\n// See https://github.com/JetBrains/gradle-intellij-plugin/\nintellij {\n//    version '2019.1.4'\n//    Adjust when toolbox update IDEA app\n    localPath System.getenv(\"IDEA_HOME\")\n    plugins = ['java'] //Bundled plugin dependencies\n    pluginName 'D8gerAutoCode'\n    updateSinceUntilBuild false\n    sandboxDirectory = \"${project.rootDir}/.sandbox\"\n}\npatchPluginXml {\n    changeNotes \n    \"\"\"\n        What encounter to pain me ever belongs to see you now.<br>\n        <br>\n        Plug-in new revision, new features and high performance.<br>\n        One-click to handle multi-lines, isn't cool?<br>\n        One-click to beauty MySQL, isn't fragrant?<br>\n        It's very sure that you deserve to use.<br>\n    \"\"\"\n}"
  },
  {
    "path": "doc/ComputerMathData.md",
    "content": "# MarkDown 数学公式语法大全\n- 单行左对齐公式\n$\\sum_{i=0}^N\\int_{a}^{b}g(t,i)\\text{d}t$\n\n- 跨行居中公式\n$$\n\\sum_{i=0}^N\\int_{a}^{b}g(t,i)\\text{d}t\n$$\n\n- 无边框矩阵\n$$\n\\begin{matrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{matrix}\n$$\n\n- 小括号边框矩阵\n$$\n\\begin{pmatrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{pmatrix}\n$$\n\n- 大括号边框矩阵\n$$\n\\begin{Bmatrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{Bmatrix}\n$$\n\n- 双竖线边框矩阵\n$$\n\\begin{Vmatrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{Vmatrix}\n$$\n\n- 中括号边框矩阵\n$$\n\\begin{bmatrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{bmatrix}\n$$\n\n- 行列式边框矩阵\n$$\n\\begin{vmatrix}\n1 & 0 & 0 \\\\  \n0 & 1 & 0 \\\\  \n0 & 0 & 1 \\\\  \n\\end{vmatrix}\n$$\n\n- m*n省略号矩阵\n$$\n\\begin{bmatrix}\n{a_{11}}&{a_{12}}&{\\cdots}&{a_{1n}} \\\\\n{a_{21}}&{a_{22}}&{\\cdots}&{a_{2n}} \\\\\n{\\vdots}&{\\vdots}&{\\ddots}&{\\vdots} \\\\\n{a_{m1}}&{a_{m2}}&{\\cdots}&{a_{mn}} \\\\\n\\end{bmatrix}\n$$\n\n- 常用集合符号函数矩阵\n$$\n\\begin{bmatrix}\n{\\sin x}&{\\ln x}&{\\max(A,B)}&{\\infty}&{\\cup} \\\\\n{\\cap}&{\\subset}&{\\subseteq}&{\\supset}&{\\in} \\\\\n{\\notin}&{\\varnothing}&{\\forall}&{\\exists}&{\\lnot} \\\\\n{\\nabla}&{\\partial}&{a \\quad b}&{a \\ b}&{a_{xyz}} \\\\\n\\end{bmatrix}\n$$\n\n\n\n- 常用微积分符号矩阵\n$$\n\\begin{pmatrix}\n{\\sum_{i=1}^n{a_i}}&{\\prod \\frac{1}{i^2}}&{\\lim_{x\\to 0}}&{\\prime} \\\\\n{\\int_0^\\infty{f(x)dx}}&{\\mathrm{d}}&{\\int ^2_3 x^2 {rm d}x}&{\\iint} \\\\\n{\\iiiint}&{\\oint}{\\frac{x}{y}}&&{\\sqrt[x]{y}} \\\\\n\\end{pmatrix}\n$$\n\n\n\n\n\n\n- 泰勒级数\n$$\ne^{x} = 1 + \\frac{x}{1!} + \\frac{x^{2}}{2!} + \\frac{x^{3}}{3!} + \\cdots , \\quad - \\infty < x < \\infty\n$$\n\n- 余弦公式\n$$\n\\cos 2\\theta = \\cos^2 \\theta - \\sin^2 \\theta = 2 \\cos^2 \\theta\n$$ \n\n- 集合公式 \n$$\nM(\\beta^{\\ast}(D),D) \\subseteq C\n$$\n\n- 求和公式  \n$$\n\\sum_{i=0}^n i^2 = \\frac{(n^2+n)(2n+1)}{6}\n$$\n\n- 平方根公式  \n$$\nx = \\dfrac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}\n$$  \n\n- 条件函数\n$$\nf(n) =\n\\begin{cases}\n\\frac{n}{2},  & \\text{if $n$ is even} \\\\\n3n+1, & \\text{if $n$ is odd}\n\\end{cases}\n$$\n\n- 偏导数公式\n$$\n\\begin{equation}\n\\begin{split}\n\\frac{\\partial^2 f}{\\partial{x^2}} &= \\frac{\\partial(\\Delta_x f(i,j))}{\\partial x} = \\frac{\\partial(f(i+1,j)-f(i,j))}{\\partial x} \\\\\n&= \\frac{\\partial f(i+1,j)}{\\partial x} - \\frac{\\partial f(i,j)}{\\partial x} \\\\\n&= f(i+2,j) -2f(f+1,j) + f(i,j)\n\\end{split}\n\\nonumber\n\\end{equation}\n$$\n\n- 统计学公式带编号\n$$\n\\begin{equation}\n\\sum_{i=0}^n F_i \\cdot \\phi (H, p_i) - \\sum_{i=1}^n a_i \\cdot ( \\tilde{x_i}, \\tilde{y_i}) + b_i \\cdot ( \\tilde{x_i}^2 , \\tilde{y_i}^2 ) \\tag{1.2.3}\n\\end{equation}\n$$\n\n$$\n\\begin{equation}\n\\beta^*(D) = \\mathop{argmin} \\limits_{\\beta} \\lambda {||\\beta||}^2 + \\sum_{i=1}^n max(0, 1 - y_i f_{\\beta}(x_i)) \\tag{1.2.4}\n\\end{equation}\n$$\n\n\n$$\n\\begin{equation}\n\\sum_{i=0}^n F_i \\cdot \\phi (H, p_i) - \\sum_{i=1}^n a_i \\cdot ( \\tilde{x_i}, \\tilde{y_i}) + b_i \\cdot ( \\tilde{x_i}^2 , \\tilde{y_i}^2 ) \\tag{1.2.5}\n\\end{equation}\n$$\n\n\n$$\n\\beta^*(D) = \\mathop{argmin} \\limits_{\\beta} \\lambda {||\\beta||}^2 + \\sum_{i=1}^n max(0, 1 - y_i f_{\\beta}(x_i)) \\tag{1.2.6}\n$$\n\n$$z = (p_0, ..... , p_n) \\tag{公式21} $$  \n$$ s = r cos(a+b) = r cos(a) cos(b) - r sin(a) sin(b) \\tag{1.1} $$  \n$$ t = r sin(a+b) = r sin(a) cos(b) - r cos(a) sin(b) \\tag{1.2} $$\n\n- 极限\n$$ \\max \\limits_{a<x<b}\\{f(x)\\} $$\n\n- 好玩矩阵\n$$\n\\begin{matrix}\n{\\lceil \\frac{x}{2} \\rceil} & {\\lfloor \\frac{x}{2} \\rfloor} & x^2 \\\\\n{\\lbrace \\rbrace} & {\\langle,\\rangle} & y^2 \\\\\n{\\mathop{a}\\limits_{i=1}} & z & z^2 \\\\\n\\end{matrix}\n$$\n\n- 行内小矩阵\n$$\\bigl( \\begin{smallmatrix} a & b \\\\ c & d \\end{smallmatrix} \\bigr)$$\n\n- 数组带分割线\n$$\n\\left[\n    \\begin{array}{cc|c}\n      1&2&3\\\\\n      4&5&6\n    \\end{array}\n\\right] \n$$\n\n- 矩阵方程表达式\n$$\n\\left(\n\\begin{array}{c}\n      s \\\\\n      t\n\\end{array}\n\\right)\n=\\left[\n\\begin{array}{cc}\n      cos(b) & -sin(b) \\\\\n      sin(b) & cos(b)\n\\end{array}\n\\right]\n*\\left(\n    \\begin{array}{c}\n      x \\\\\n      y\n    \\end{array}\n\\right)\n$$\n\n- 向量表达式\n$$\n\\begin{bmatrix}\n      {\\vec {x}} \\\\\n      {\\overrightarrow {x}} \\\\\n      {\\overrightarrow {xyzcfcfcf}} \\\\\n      {\\overleftarrow {xyzcfcfcfcfcf}}\n      {x^2} \\\\\n      {x_i} \\\\\n      {x_{n^2}^{2_n}}\n\\end{bmatrix}\n$$\n\n- 常用希腊字母表达式\n$$\n\\begin{bmatrix}\n\t\t{\\alpha}&{\\beta}&{\\gamma}&{\\delta}&{\\epsilon}&{\\zeta}&{\\eta}&{\\theta} \\\\\n\t\t{\\lambda}&{\\mu}&{\\nu}&{\\xi}&{\\pi}&{\\rho}&{\\sigma}&{\\kappa} \\\\\n\t\t{\\upsilon}&{\\phi}&{\\chi}&{\\psi}&{\\omega}&{\\tau}&{\\iota}&{0} \\\\\n\t\t{\\Sigma}&{\\Theta}&{\\Gamma}&{\\Delta}&{\\Lambda}&{\\Xi}&{\\Pi}&{\\Upsilon} \\\\\n\t\t{\\Phi}&{\\Psi}&{\\Omega}&{0}&{0}&{0}&{0}&{0}\n\\end{bmatrix}\n$$\n\n\n\n## 参考\n[MarkDown公式语法](https://www.jianshu.com/p/a0aa94ef8ab2)  \n[MarkDown公式语法2](https://cloud.tencent.com/developer/article/1402840)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "doc/Math.adoc",
    "content": "== Math\n- A\n\\begin{equation}\n\\left[\\begin{array}{cccccc}\n{a_{11}} & {a_{12}} & {\\cdots} & {a_{1 n}} \\\\\n{a_{21}} & {a_{22}} & {\\cdots} & {a_{2 n}} \\\\\n{\\vdots} & {\\vdots} & {\\ddots} & {\\vdots} \\\\\n{\\sin x} & {\\ln x} & {\\cdots} & {\\vdots} \\\\\n{-} & {c} & {} & {\\underline{c}} & {\\supset} & {\\epsilon} \\\\\n{} & {\\varnothing} & {} & {\\Psi} & {\\exists} & {\\ddots} \\\\\n{\\nabla} & {\\partial} & {} & {a} & {b_{3}} & {a b} & {a_{x y z}}\n\\end{array}\\right]\n\\end{equation}\n\n- B\n\\(\\left[\\begin{array}{cccccc}{a_{11}} & {a_{12}} & {\\cdots} & {a_{1 n}} \\\\ {a_{21}} & {a_{22}} & {\\cdots} & {a_{2 n}} \\\\ {\\vdots} & {\\vdots} & {\\ddots} & {\\vdots} \\\\ {\\sin x} & {\\ln x} & {\\cdots} & {\\vdots} \\\\ {-} & {c} & {} & {\\underline{c}} & {\\supset} & {\\epsilon} \\\\ {} & {\\varnothing} & {} & {\\Psi} & {\\exists} & {\\ddots} \\\\ {\\nabla} & {\\partial} & {} & {a} & {b_{3}} & {a b} & {a_{x y z}}\\end{array}\\right]\\)\n\n- C\n\\begin{equation}\n\\sum_{i=0}^{N} \\int_{a}^{b} g(t, i) \\mathrm{d} t\n\\end{equation}\n\n- D\n\\begin{equation}\n\\frac{\\partial^{2} f}{\\partial x^{2}}=\\frac{\\partial\\left(\\Delta_{\\mathcal{X}} f(i, j)\\right)}{\\partial x}=\\frac{\\partial(f(i+1, j)-f(i, j))}{\\partial x}=\\frac{\\partial f(i+1, j)}{\\partial x}-\\frac{\\partial f(i, j)}{\\partial x}=f(i+2, j)-2 f(f+1, j)+f(i, j)\n\\end{equation}\n\n- E\n"
  },
  {
    "path": "doc/WX-MarkDownTest.md",
    "content": "# 示例文章：Google 搜索的即时自动补全功能究竟是如何“工作”的？\n> Google 搜索**自动补全功能**的强大，相信不少朋友都能感受到，它帮助我们更快地“补全”我们所要输入的搜索关键字。那么，它怎么知道我们要输入什么内容？它又是如何工作的？在这篇文章里，我们一起来看看。\n\n## 使用自动补全\nGoogle 搜索的自动补全功能可以在 Google 搜索应用的大多数位置使用，包括 [Google](https://www.google.com/) 主页、适用于 IOS 和 Android 的 Google 应用，我们只需要在 Google 搜索框上开始键入关键字，就可以看到联想词了。\n\n![](https://imgkr.cn-bj.ufileos.com/17ed83bf-e028-4db2-9503-5a3b4e64deee.gif)\n\n在上图示例中，我们可以看到，输入关键字 `juej`，Google 搜索会联想到“掘金”、“掘金小册”、“绝句”等等，好处就是，我们无须输入完整的关键字即可轻松完成针对这些 topics 的搜索。\n\n谷歌搜索的自动补全功能对于使用移动设备的用户来说特别有用，用户可以轻松在难以键入的小屏幕上完成搜索。当然，对于移动设备用户和台式机用户而言，这都节省了大量的时间。根据 Google 官方报告，自动补全功能可以减少大约 25% 的打字，累积起来，预计每天可以节省 200 多年的打字时间。是的，每天！\n\n> 注意，本文所提到的“**联想词**”与“**预测**”，是同一个意思。\n\n## 基于“预测”而非“建议”\nGoogle 官方将自动补全功能称之为“预测”，而不是“建议”，为什么呢？其实是有充分理由的。自动补全功能是为了**帮助用户完成他们打算进行的搜索**，而不是建议用户要执行什么搜索。\n\n那么，Google 是如何确定这些“预测”的？其实，Google 会根据趋势搜索 [trends](https://trends.google.com/trends/?geo=US) 给到我们这些“预测”。简单来说，哪个热门、哪个搜索频率高，就更可能推给我们。当然，这也与我们当前所处的位置以及我们的搜索历史相关。\n\n另外，这些“预测”也会随着我们键入的关键字的变更而更改。例如，当我们把键入的关键字从 `juej` 更改为 `juex` 时，与“掘金”相关的预测会“消失”，同时，与“觉醒”、“决心”相关联的词会出现。\n\n![](https://imgkr.cn-bj.ufileos.com/5b17dc99-606d-42c1-9f86-e09e88aaa822.gif)\n\n## 为什么看不到某些联想词？\n如果我们在输入某个关键字时看不到联想词，那么表明 Google 的算法可能检测到：\n\n- 这个关键字不是热门字词；\n- 搜索的字词太新了，我们可能需要等待几天或几周才能看到联想词；\n- 这是一个侮辱性或敏感字词，这个搜索字词违反了 Google 的相关政策。更加详细的情况，可以了解 [Google 搜索自动补全政策](https://support.google.com/websearch/answer/7368877)。\n\n## 为什么会看到某些不当的联想词？\nGoogle 拥有专门设计的系统，可以自动捕获不适当的预测结果而不显示出来。然而，Google 每天需要处理数十亿次搜索，这意味着 Google 每天会显示数十亿甚至上百亿条预测。再好的系统，也可能存在缺陷，不正确的预测也可能随时会出现。\n\n我们作为 Google 搜索的用户，如果认定某条预测违反了相关的搜索自动补全政策，可以进行举报反馈，点击右下角“**举报不当的联想查询**”并勾选相关选项即可。\n\n![](https://imgkr.cn-bj.ufileos.com/6ca8185d-12c6-4550-bb4e-e49cfbf56db7.gif)\n\n## 如何实现自动补全算法？\n目前，Google 官方似乎并没有公开搜索自动补全的算法实现，但是业界在这方面已经有了不少研究。\n\n一个好的自动补全器必须是快速的，并且在用户键入下一个字符后立即更新联想词列表。**自动补全器的核心是一个函数，它接受输入的前缀，并搜索以给定前缀开头的词汇或语句列表**。通常来说，只需要返回少量的数目即可。\n\n接下来，我们先从一个简单且低效的实现开始，并在此基础上逐步构建更高效的方法。\n\n### 词汇表实现\n一个**简单粗暴的实现方式**是：顺序查找词汇表，依次检查每个词汇，看它是否以给定的前缀开头。\n\n但是，此方法需要将前缀与每个词汇进行匹配检查，若词汇量较少，这种方式可能勉强行得通。但是，如果词汇量规模较大，效率就太低了。\n\n一个**更好的实现方式是**：让词汇按字典顺序排序。借助二分搜索算法，可以快速搜索有序词汇表中的前缀。由于二分搜索的每一步都会将搜索的范围减半，因此，总的搜索时间与词汇表中单词数量的对数成正比，即时间复杂度是 `O(log N)`。二分搜索的性能很好，但有没有更好的实现呢？当然有，往下看。\n\n### 前缀树实现\n通常来说，许多词汇都以相同的前缀开头，比如 `need`、`nested` 都以 `ne` 开头，`seed`、`speed` 都以 `s` 开头。要是为每个单词分别存储公共前缀似乎很浪费。\n\n![](https://imgkr.cn-bj.ufileos.com/7cc3cf37-040a-420e-8ef9-d05e92c82cfd.png)\n\n前缀树是一种利用公共前缀来加速补全速度的数据结构。前缀树在节点树中排列一组单词，单词沿着从根节点到叶子节点的路径存储，树的层次对应于前缀的字母位置。\n\n前缀的补全是顺着前缀定义的路径来查找的。例如，在上图的前缀树中，前缀 `ne` 对应于从子节点取左边缘 `N` 和唯一边缘 `E` 的路径。然后可以通过继续遍历从 `E` 节点可以达到的所有叶节点来生成补全列表。在图中，`ne` 的补全可以是两个分支：`-ed` 和 `-sted`。如果在数中找不到由前缀定义的路径，则说明词汇表中不包含以该前缀开头的单词。\n\n### 有限状态自动机(DFA)实现\n前缀树可以有效处理公共前缀，但是，对于其他共享词部分，仍会分别存储在每个分支中。比如，后缀 `ed`、`ing`、`tion` 在英文单词中特别常见。在上一个例子中，`e`、`d` 分别存放在了每一个分支上。\n\n有没有一种方法可以更加节省存储空间呢？有的，那就是 DFA。\n\n<center>\n<img src=\"https://imgkr.cn-bj.ufileos.com/02bc143e-e1a7-4b3c-bd5d-8d6d39139f0a.png\" style=\"width: 50%;\"></center>\n\n在上面的例子中，单词 `need`、`nested`、`seed` 和 `speed` 仅由 9 个节点组成，而上一张图中的前缀树包含了 17 个节点。\n\n可以看出，最小化前缀树 DFA 可以在很大程度上减少数据结构的大小。即使词汇量很大，最小化 DFA 通常也适合在内存中存储，避免昂贵的磁盘访问是实现快速自动补全的关键。\n\n### 一些扩展\n上面介绍了如何利用合理的数据结构实现基本的自动补全功能。这些数据结构可以通过多种方式进行扩展，从而改善用户体验。\n\n通常，满足特定前缀的词汇可能很多，而用户界面上能够显示的却不多，我们更希望能显示最常搜索或者最有价值的词汇。这通常可以通过为词汇表中的每个单词增加一个代表单词值的**权重** `weight`，并且按照权重高低来排序自动补全列表。\n\n- 对于排序后的词汇表来说，在词汇表每个元素上增加 `weight` 属性并不难；\n- 对于前缀树来说，将 `weight` 存储在叶子节点中，也是很简单的一个实现；\n- 对于 `DFA` 来说，则较为复杂。因为一个叶子节点可以通过多条路径到达。一种解决方案是将权重关联到路径而不是叶子节点。\n\n目前有不少开源库都提供了这个功能，比如主流的搜索引擎框架 [Elasticsearch](https://www.elastic.co/products/elasticsearch)、[Solr](https://lucene.apache.org/solr/) 等，基于此，我们可以实现高效而强大的自动补全功能。\n\n#### 推荐阅读\n- [A: 原文链接](https://doocs.github.io/md/)\n- [阿里又一个 20k+ stars 开源项目诞生，恭喜 fastjson！](https://mp.weixin.qq.com/s/RNKDCK2KoyeuMeEs6GUrow)\n- [刷掉 90% 候选人的互联网大厂海量数据面试题（附题解 + 方法总结）](https://mp.weixin.qq.com/s/rjGqxUvrEqJNlo09GrT1Dw)\n- [好用！期待已久的文本块功能究竟如何在 Java 13 中发挥作用？](https://mp.weixin.qq.com/s/kalGv5T8AZGxTnLHr2wDsA)\n- [2019 GitHub 开源贡献排行榜新鲜出炉！微软谷歌领头，阿里跻身前 12！](https://mp.weixin.qq.com/s/_q812aGD1b9QvZ2WFI0Qgw)\n- [哈哈](http://file.debuggerpowerzcy.top/power/)\n---\n\n欢迎关注我的公众号“**Doocs开源社区**”，原创技术文章第一时间推送。\n\n<center>\n    <img src=\"https://imgkr.cn-bj.ufileos.com/1092dc45-e817-4bb0-82b0-2b2b4826ccf2.gif\" style=\"width: 100px;\">\n</center>\n\n```\nNext generation plan\n(backup: autoCode -> {\n(MAPPER + XML层)\n    var1: insertWithIdSelective\n          selectByExampleWithBLOBs\n          updateByExampleWithBLOBs\n          updateByPrimaryKeyWithBLOBs\n(SERVICE层)\n          selectByPrimaryKey\n          deleteByPrimaryKey\n          updateByPrimaryKey\n    var2: @ID, @SECOND_MAIN_KEY\n          @UNIQ(group, order), @INDEX, @UNIQ_INDEX(group, order),\n          @NOTNULL, @DEFAULT,\n          @BLOB\n    var3: CreateTime | UpdateTime(, bug?) 禁用配置\n    var4: caofanCPU-branch, private\n    var5: digital automatic\n    var6: bug fix, d8gerDir?\n})\n\n优先级\n1.XML insertWithIdSelective\n2.CreateTime | UpdateTime(, bug?) 禁用配置\n3.Example支持limit 1\n\n索引及其他标识, 交由用户自定义\n大文本后期再处理\n\npid=`ps aux |grep newreport |grep -v grep| awk '{print }'`\nif [ -n \"$pid\" ];then\n    kill -9 $pid\n    sleep 5\nfi\n\nrm -rf newreport-*.jar\nscp\n\n```"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'D8gerAutoCode'\n\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/WhoAmI.java",
    "content": "package com.xyz.caofancpu.d8ger;\n\n/**\n * Who You Are?\n */\npublic class WhoAmI {\n\n    /**\n     * ID\n     */\n    private Long id;\n\n    private Integer age;\n\n    private String name;\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/action/D8gerAutoCodeAction.java",
    "content": "package com.xyz.caofancpu.d8ger.action;\n\nimport com.intellij.notification.Notification;\nimport com.intellij.notification.NotificationType;\nimport com.intellij.notification.Notifications;\nimport com.intellij.openapi.actionSystem.AnAction;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.command.WriteCommandAction;\nimport com.intellij.psi.PsiClass;\nimport com.intellij.psi.PsiDirectory;\nimport com.intellij.psi.PsiJavaFile;\nimport com.xyz.caofancpu.d8ger.core.AutoCodeTemplate;\nimport com.xyz.caofancpu.d8ger.core.D8gerAutoCoding;\nimport com.xyz.caofancpu.d8ger.core.KeyEnum;\nimport com.xyz.caofancpu.d8ger.core.ProjectEnvHandler;\nimport com.xyz.caofancpu.d8ger.core.TemplateKeyWordEnum;\nimport com.xyz.caofancpu.d8ger.util.CollectionUtil;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport com.xyz.caofancpu.d8ger.util.IdeaPlatformFileTreeUtil;\nimport com.xyz.caofancpu.d8ger.util.PropertiesUtil;\nimport lombok.NonNull;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\n\n/**\n * ACP(AutoCodingProgramming)\n *\n * @author caofanCPU\n */\npublic class D8gerAutoCodeAction extends AnAction {\n\n    @Override\n    public synchronized void actionPerformed(@NonNull final AnActionEvent e) {\n        D8gerAutoCoding d8gerAutoCoding = ProjectEnvHandler.checkAndInitEnv(e);\n        if (Objects.isNull(d8gerAutoCoding)) {\n            return;\n        }\n        // Create directory | file\n        WriteCommandAction.runWriteCommandAction(d8gerAutoCoding.getCurrentProject(), () -> generateAutoCodeFile(d8gerAutoCoding));\n    }\n\n    /**\n     * Perform file creation, all directory | file write operations must be inside this method,\n     * and externally use WriteCommandAction.runWriteCommandAction for wrapping\n     *\n     * @param d8gerAutoCoding\n     */\n    public void generateAutoCodeFile(D8gerAutoCoding d8gerAutoCoding) {\n        List<String> fileNameList = new ArrayList<>();\n        // 1.Complete directory and package data\n        d8gerAutoCoding.getFileMap().keySet().forEach(key -> {\n            Pair<PsiDirectory, String> packagePair = d8gerAutoCoding.getCustomConfigAutoCodeDirMap().get(key);\n            if (Objects.isNull(packagePair)) {\n                if (d8gerAutoCoding.getRealNeedCreateFileKeyList().contains(key) && !d8gerAutoCoding.isUseDefaultDirectory()) {\n                    // Create D8AutoCode directory\n                    PsiDirectory d8gerAutoCodeDir = IdeaPlatformFileTreeUtil.getOrCreateSubDir(d8gerAutoCoding.getD8AutoCodeDir(), ConstantUtil.GENERATE_DIR);\n                    d8gerAutoCoding.setD8AutoCodeDir(d8gerAutoCodeDir);\n                    d8gerAutoCoding.setUseDefaultDirectory(true);\n                    fileNameList.add(d8gerAutoCoding.getD8AutoCodeDir().getName());\n                }\n                d8gerAutoCoding.getCustomConfigAutoCodeDirMap().put(key, Pair.of(d8gerAutoCoding.getD8AutoCodeDir(), d8gerAutoCoding.getPackageName()));\n            }\n        });\n\n        // 2.Replace keyword data\n        handleCustomPackageKeyWordMap(d8gerAutoCoding);\n\n        // 3.Just force file\n        d8gerAutoCoding.getFileMap().forEach((key, pair) -> {\n            if (skipCurrentOperation(d8gerAutoCoding, key)) {\n                // don't create file\n                return;\n            }\n            PsiDirectory targetDirectory = d8gerAutoCoding.getCustomConfigAutoCodeDirMap().get(key).getLeft();\n            PsiJavaFile autoCodeFile = IdeaPlatformFileTreeUtil.forceCreateJavaFile(\n                    targetDirectory,\n                    d8gerAutoCoding.getCurrentProject(),\n                    pair.getLeft(),\n                    AutoCodeTemplate.render(pair.getRight(), d8gerAutoCoding.loadEnhanceKeyWordMap(key))\n            );\n            // Find and import enum classes\n            if (KeyEnum.needImportEnumClass(key)) {\n                d8gerAutoCoding.getEnumTypeClassName().forEach(item -> {\n                    Optional<PsiClass> optionalPsiClass = IdeaPlatformFileTreeUtil.findClass(d8gerAutoCoding.getCurrentProject(), item);\n                    optionalPsiClass.ifPresent(autoCodeFile::importClass);\n                    if (!skipCurrentOperation(d8gerAutoCoding, KeyEnum.FORMAT_STYLE)) {\n                        // do code formatting\n                        IdeaPlatformFileTreeUtil.format(d8gerAutoCoding.getCurrentProject(), autoCodeFile);\n                    }\n                });\n            }\n            // This step is very important which would cause fail of creating file if it was ignored\n            targetDirectory.add(autoCodeFile);\n            fileNameList.add(autoCodeFile.getName());\n        });\n\n        Notifications.Bus.notify(\n                new Notification(ConstantUtil.NOTIFICATION_GROUP_VIEW_ID, \"Look Rebuilding file here\", CollectionUtil.join(fileNameList, ConstantUtil.DOUBLE_NEXT_LINE), NotificationType.INFORMATION)\n        );\n    }\n\n    /**\n     * Skip current operation or not\n     *\n     * @param d8gerAutoCoding\n     * @param keyEnum\n     * @return\n     */\n    private boolean skipCurrentOperation(D8gerAutoCoding d8gerAutoCoding, KeyEnum keyEnum) {\n        return !PropertiesUtil.checkConfigTakeEffect(d8gerAutoCoding.loadPropertiesFromRootResource(), keyEnum.getKey());\n    }\n\n    /**\n     * Handle replacing package names by custom directory configs\n     */\n    private void handleCustomPackageKeyWordMap(D8gerAutoCoding d8gerAutoCoding) {\n        Map<String, StringBuilder> keyWordMatchMap = d8gerAutoCoding.getKeyWordMatchMap();\n        d8gerAutoCoding.getCustomConfigAutoCodeDirMap().forEach((key, pair) -> {\n            TemplateKeyWordEnum targetPackageKey = null;\n            switch (key) {\n                case MO:\n                    targetPackageKey = TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY;\n                    break;\n                case MO_MAPPER:\n                    targetPackageKey = TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY;\n                    break;\n                case MO_EXAMPLE:\n                    targetPackageKey = TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY;\n                    break;\n                case SWAGGER_MO:\n                    targetPackageKey = TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY;\n                    break;\n                case MO_HANDLER:\n                    targetPackageKey = TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY;\n                    break;\n                case MO_CONTROLLER:\n                    targetPackageKey = TemplateKeyWordEnum.CONTROLLER_PACKAGE_NAME_KEY;\n                    break;\n                default:\n                    break;\n            }\n            if (Objects.nonNull(targetPackageKey)) {\n                keyWordMatchMap.put(targetPackageKey.getName(), new StringBuilder(pair.getRight()));\n            }\n        });\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/action/SwaggerModelAutoRenderAction.java",
    "content": "package com.xyz.caofancpu.d8ger.action;\n\nimport com.intellij.openapi.actionSystem.AnAction;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.actionSystem.CommonDataKeys;\nimport com.intellij.openapi.command.WriteCommandAction;\nimport com.intellij.openapi.editor.Document;\nimport com.intellij.openapi.editor.Editor;\nimport com.intellij.openapi.project.Project;\nimport com.xyz.caofancpu.d8ger.util.CollectionUtil;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil;\nimport lombok.NonNull;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * SwaggerModel model automatic rendering\n *\n * @author caofanCPU\n */\npublic class SwaggerModelAutoRenderAction extends AnAction {\n    @Override\n    public void actionPerformed(AnActionEvent e) {\n        final Editor currentEditor = e.getRequiredData(CommonDataKeys.EDITOR);\n        final Project currentProject = e.getRequiredData(CommonDataKeys.PROJECT);\n        final Document currentDocument = currentEditor.getDocument();\n\n        // Perform a refresh of the current file\n        WriteCommandAction.runWriteCommandAction(currentProject, () -> executeSwaggerRender(currentDocument));\n    }\n\n    /**\n     * Rewrite file\n     *\n     * @param currentDocument\n     */\n    public void executeSwaggerRender(@NonNull Document currentDocument) {\n        // split lines by \\n | \\r\\n\n        String[] codeLines = currentDocument.getText().split(\"(?:\\\\n|(?:\\\\r\\\\n))\");\n        List<String> wrapLineList = new ArrayList<>(codeLines.length);\n        int apiModelPropertyCounter = 0;\n        int apiOperationSupportCounter = 0;\n        for (String item : codeLines) {\n            // case 1\n            if (item.contains(\"@ApiModelProperty(\")) {\n                if (!item.contains(\"position\")) {\n                    String replacer = (item.contains(\"()\") ? \"position = \" : \", position = \") + (++apiModelPropertyCounter) + \")\";\n                    item = item.replace(\")\", replacer);\n                } else {\n                    item = VerbalExpressionUtil.regexHandleSwaggerModelProperty(item, \"position = \" + (++apiModelPropertyCounter));\n                }\n            }\n\n            // case 2\n            if (item.contains(\"@ApiOperationSupport(\")) {\n                if (!item.contains(\"order\")) {\n                    String replacer = (item.contains(\"()\") ? \"order = \" : \", order = \") + (++apiOperationSupportCounter) + \")\";\n                    item = item.replace(\")\", replacer);\n                } else {\n                    item = VerbalExpressionUtil.regexHandleSwaggerModelProperty(item, \"order = \" + (++apiOperationSupportCounter));\n                }\n            }\n            wrapLineList.add(item);\n        }\n        boolean isWindowsLinebreak = currentDocument.getText().contains(ConstantUtil.WINDOWS_NEXT_LINE);\n        currentDocument.setText(CollectionUtil.join(wrapLineList, isWindowsLinebreak ? ConstantUtil.WINDOWS_NEXT_LINE : ConstantUtil.NEXT_LINE));\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/activity/D8gerActivity.java",
    "content": "package com.xyz.caofancpu.d8ger.activity;\n\nimport com.intellij.ide.plugins.IdeaPluginDescriptor;\nimport com.intellij.ide.plugins.PluginManagerCore;\nimport com.intellij.notification.Notification;\nimport com.intellij.notification.NotificationType;\nimport com.intellij.notification.Notifications;\nimport com.intellij.openapi.application.ApplicationManager;\nimport com.intellij.openapi.extensions.PluginId;\nimport com.intellij.openapi.project.DumbAware;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.startup.StartupActivity;\nimport com.intellij.util.text.VersionComparatorUtil;\nimport com.xyz.caofancpu.d8ger.setting.D8gerApplicationState;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.Objects;\n\n/**\n * Start up and update activity, show some message!\n *\n * @author D8GER\n */\npublic class D8gerActivity implements StartupActivity, DumbAware {\n\n    @Override\n    public void runActivity(@NotNull Project project) {\n        if (ApplicationManager.getApplication().isUnitTestMode()) {\n            return;\n        }\n        IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(PluginId.getId(ConstantUtil.PLUGIN_ID));\n        if (Objects.nonNull(plugin)) {\n            String installedVersion = D8gerApplicationState.getOldVersion();\n            int compare = VersionComparatorUtil.compare(installedVersion, plugin.getVersion());\n            if (compare < 0) {\n                ApplicationManager.getApplication()\n                        .invokeLater(() -> Notifications.Bus.notify(\n                                new Notification(ConstantUtil.NOTIFICATION_GROUP_VIEW_ID,\n                                        ConstantUtil.RENDER_TITLE + \"    (Update To v\" + plugin.getVersion() + \")\",\n                                        \"If you like D8gerAutoCode, please star the project <a href='https://github.com/caofanCPU/D8gerAutoCode'>D8gerAutoCode</a>\",\n                                        NotificationType.INFORMATION\n                                ))\n                        );\n                D8gerApplicationState.setPluginVersion(plugin.getVersion());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/AutoCodeTemplate.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\nimport com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil;\nimport lombok.NonNull;\nimport ru.lanwen.verbalregex.VerbalExpression;\n\nimport java.util.Map;\n\n/**\n * Code template string constants\n *\n * @author caofanCPU\n */\npublic class AutoCodeTemplate {\n    public static Boolean IS_EN_LOCALE = Boolean.TRUE;\n\n    /**\n     * MO template string\n     */\n    public static StringBuilder ZN_TEMPLATE_MO = new StringBuilder(\"package @moPackage@;\\n\" +\n            \"\\n\" +\n            \"import lombok.AllArgsConstructor;\\n\" +\n            \"import lombok.Data;\\n\" +\n            \"import lombok.NoArgsConstructor;\\n\" +\n            \"import lombok.experimental.Accessors;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Data\\n\" +\n            \"@NoArgsConstructor\\n\" +\n            \"@AllArgsConstructor\\n\" +\n            \"@Accessors(chain = true)\\n\" +\n            \"public class @MoName@Mo {\\n\" +\n            \"\\n\" +\n            \"@field@\\n\" +\n            \"\\n\" +\n            \"}\");\n\n    /**\n     * Swagger VO template string\n     */\n    public static StringBuilder ZN_TEMPLATE_SWAGGER_VO = new StringBuilder(\"package @swaggerMoPackage@;\\n\" +\n            \"\\n\" +\n            \"import io.swagger.annotations.ApiModel;\\n\" +\n            \"import io.swagger.annotations.ApiModelProperty;\\n\" +\n            \"import lombok.AllArgsConstructor;\\n\" +\n            \"import lombok.Data;\\n\" +\n            \"import lombok.NoArgsConstructor;\\n\" +\n            \"import lombok.experimental.Accessors;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo对应的SwaggerApi增强Vo对象\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Data\\n\" +\n            \"@NoArgsConstructor\\n\" +\n            \"@AllArgsConstructor\\n\" +\n            \"@Accessors(chain = true)\\n\" +\n            \"@ApiModel\\n\" +\n            \"public class @MoName@Vo {\\n\" +\n            \"\\n\" +\n            \"@swaggerField@\\n\" +\n            \"\\n\" +\n            \"}\");\n\n    /**\n     * Sql template string\n     */\n    public static StringBuilder ZN_TEMPLATE_MO_SQL = new StringBuilder(\"\\n\" +\n            \"-- ----------------------------\\n\" +\n            \"-- D8ger-Sql-Auto-Generated\\n\" +\n            \"-- Table structure for `@mo_table_name@`\\n\" +\n            \"-- @author @d8Author@\\n\" +\n            \"-- ----------------------------\\n\" +\n            \"-- DROP TABLE IF EXISTS `@mo_table_name@`;\\n\" +\n            \"CREATE TABLE `@mo_table_name@`\\n\" +\n            \"(\\n\" +\n            \"@sql_column@\\n\" +\n            \")\\n\" +\n            \"    comment '@MoName@表' charset = utf8mb4;\\n\");\n\n    /**\n     * Mapper template string\n     */\n    public static StringBuilder ZN_TEMPLATE_MAPPER = new StringBuilder(\"package @mapperPackage@;\\n\" +\n            \"\\n\" +\n            \"import @moExamplePackage@.@MoName@Example;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import org.apache.ibatis.annotations.Param;\\n\" +\n            \"import @MapperAnnotationPackage@;\\n\" +\n            \"\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo对应的Mapper\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@MapperAnnotation@\\n\" +\n            \"public interface @MoName@Mapper {\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据条件查询列表\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 批量更新, 根据主键更新非null字段\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据条件更新非null字段\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateByExampleSelective(@Param(\\\"record\\\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\\\"example\\\") @MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据条件删除记录\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据条件统计记录\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return 记录条数\\n\" +\n            \"     */\\n\" +\n            \"    int countByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 增加单条记录, 并为入参设置ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 批量增加记录, 并为入参设置ID\\n\" +\n            \"     * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * @MoName@列表查询\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据ID查询对象\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    <T extends Number> @MoName@Mo selectByPrimaryKey(T id);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据主键只更新非null字段\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据ID删除记录\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    <T extends Number> int deleteByPrimaryKey(T id);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据条件查询单个对象\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 增加单条非空字段记录, 并为入参设置ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"}\");\n\n    /**\n     * MoExample template string\n     */\n    public static StringBuilder ZN_TEMPLATE_MO_EXAMPLE = new StringBuilder(\"package @moExamplePackage@;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.ArrayList;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo对应的Example单表操作对象\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"public class @MoName@Example {\\n\" +\n            \"\\n\" +\n            \"    protected String orderByClause;\\n\" +\n            \"\\n\" +\n            \"    protected Integer limit;\\n\" +\n            \"\\n\" +\n            \"    protected boolean distinct;\\n\" +\n            \"\\n\" +\n            \"    protected List<Criteria> conditionCriteria;\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example() {\\n\" +\n            \"        conditionCriteria = new ArrayList<>();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andOrderByClause(String orderByClause) {\\n\" +\n            \"        this.orderByClause = orderByClause;\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public String getOrderByClause() {\\n\" +\n            \"        return orderByClause;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andLimit(Integer limit) {\\n\" +\n            \"        if (limit != null && limit > 0) {\\n\" +\n            \"            this.limit = limit;\\n\" +\n            \"        }\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Integer getLimit() {\\n\" +\n            \"        return limit;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andDistinct(boolean distinct) {\\n\" +\n            \"        this.distinct = distinct;\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public boolean isDistinct() {\\n\" +\n            \"        return distinct;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public List<Criteria> getConditionCriteria() {\\n\" +\n            \"        return conditionCriteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public void or(Criteria criteria) {\\n\" +\n            \"        conditionCriteria.add(criteria);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Criteria or() {\\n\" +\n            \"        Criteria criteria = createCriteriaInternal();\\n\" +\n            \"        conditionCriteria.add(criteria);\\n\" +\n            \"        return criteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Criteria createCriteria() {\\n\" +\n            \"        Criteria criteria = createCriteriaInternal();\\n\" +\n            \"        if (conditionCriteria.size() == 0) {\\n\" +\n            \"            conditionCriteria.add(criteria);\\n\" +\n            \"        }\\n\" +\n            \"        return criteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    protected Criteria createCriteriaInternal() {\\n\" +\n            \"        return new Criteria();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public void clear() {\\n\" +\n            \"        conditionCriteria.clear();\\n\" +\n            \"        orderByClause = null;\\n\" +\n            \"        distinct = false;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    protected abstract static class GeneratedCriteria {\\n\" +\n            \"        protected List<Criterion> criteria;\\n\" +\n            \"\\n\" +\n            \"        protected GeneratedCriteria() {\\n\" +\n            \"            super();\\n\" +\n            \"            criteria = new ArrayList<>();\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isValid() {\\n\" +\n            \"            return criteria.size() > 0;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public List<Criterion> getAllCriteria() {\\n\" +\n            \"            return criteria;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public List<Criterion> getCriteria() {\\n\" +\n            \"            return criteria;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition) {\\n\" +\n            \"            if (condition == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Value for condition cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition, Object value, String property) {\\n\" +\n            \"            if (value == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Value for \\\" + property + \\\" cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition, value));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition, Object value1, Object value2, String property) {\\n\" +\n            \"            if (value1 == null || value2 == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Between values for \\\" + property + \\\" cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition, value1, value2));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"@ExampleDefinitionMethod@\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public static class Criteria extends GeneratedCriteria {\\n\" +\n            \"        protected Criteria() {\\n\" +\n            \"            super();\\n\" +\n            \"        }\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public static class Criterion {\\n\" +\n            \"        private String condition;\\n\" +\n            \"\\n\" +\n            \"        private Object value;\\n\" +\n            \"\\n\" +\n            \"        private Object secondValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean noValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean singleValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean betweenValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean listValue;\\n\" +\n            \"\\n\" +\n            \"        private String typeHandler;\\n\" +\n            \"\\n\" +\n            \"        public String getCondition() {\\n\" +\n            \"            return condition;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public Object getValue() {\\n\" +\n            \"            return value;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public Object getSecondValue() {\\n\" +\n            \"            return secondValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isNoValue() {\\n\" +\n            \"            return noValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isSingleValue() {\\n\" +\n            \"            return singleValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isBetweenValue() {\\n\" +\n            \"            return betweenValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isListValue() {\\n\" +\n            \"            return listValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public String getTypeHandler() {\\n\" +\n            \"            return typeHandler;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.typeHandler = null;\\n\" +\n            \"            this.noValue = true;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, String typeHandler) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.value = value;\\n\" +\n            \"            this.typeHandler = typeHandler;\\n\" +\n            \"            if (value instanceof List<?>) {\\n\" +\n            \"                this.listValue = true;\\n\" +\n            \"            } else {\\n\" +\n            \"                this.singleValue = true;\\n\" +\n            \"            }\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value) {\\n\" +\n            \"            this(condition, value, null);\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.value = value;\\n\" +\n            \"            this.secondValue = secondValue;\\n\" +\n            \"            this.typeHandler = typeHandler;\\n\" +\n            \"            this.betweenValue = true;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, Object secondValue) {\\n\" +\n            \"            this(condition, value, secondValue, null);\\n\" +\n            \"        }\\n\" +\n            \"    }\\n\" +\n            \"}\");\n\n    /**\n     * Mapper.xml template string\n     */\n    public static StringBuilder ZN_TEMPLATE_MAPPER_XML = new StringBuilder(\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n\" +\n            \"<!DOCTYPE mapper PUBLIC \\\"-//mybatis.org//DTD Mapper 3.0//EN\\\" \\\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\\\">\\n\" +\n            \"<mapper namespace=\\\"@mapperPackage@.@MoName@Mapper\\\">\\n\" +\n            \"\\n\" +\n            \"    <!-- 查询操作时条件 -->\\n\" +\n            \"    <sql id=\\\"Example_Where_Clause\\\">\\n\" +\n            \"        <where>\\n\" +\n            \"            <foreach collection=\\\"conditionCriteria\\\" item=\\\"criteria\\\" separator=\\\"or\\\">\\n\" +\n            \"                <if test=\\\"criteria.valid\\\">\\n\" +\n            \"                    <trim prefix=\\\"(\\\" prefixOverrides=\\\"and\\\" suffix=\\\")\\\">\\n\" +\n            \"                        <foreach collection=\\\"criteria.criteria\\\" item=\\\"criterion\\\">\\n\" +\n            \"                            <choose>\\n\" +\n            \"                                <when test=\\\"criterion.noValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.singleValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.betweenValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.listValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                    <foreach close=\\\")\\\" collection=\\\"criterion.value\\\" item=\\\"listItem\\\" open=\\\"(\\\" separator=\\\",\\\">\\n\" +\n            \"                                        #{listItem}\\n\" +\n            \"                                    </foreach>\\n\" +\n            \"                                </when>\\n\" +\n            \"                            </choose>\\n\" +\n            \"                        </foreach>\\n\" +\n            \"                    </trim>\\n\" +\n            \"                </if>\\n\" +\n            \"            </foreach>\\n\" +\n            \"        </where>\\n\" +\n            \"    </sql>\\n\" +\n            \"\\n\" +\n            \"    <!-- 更新操作时条件 -->\\n\" +\n            \"    <sql id=\\\"Update_By_Example_Where_Clause\\\">\\n\" +\n            \"        <where>\\n\" +\n            \"            <foreach collection=\\\"example.conditionCriteria\\\" item=\\\"criteria\\\" separator=\\\"or\\\">\\n\" +\n            \"                <if test=\\\"criteria.valid\\\">\\n\" +\n            \"                    <trim prefix=\\\"(\\\" prefixOverrides=\\\"and\\\" suffix=\\\")\\\">\\n\" +\n            \"                        <foreach collection=\\\"criteria.criteria\\\" item=\\\"criterion\\\">\\n\" +\n            \"                            <choose>\\n\" +\n            \"                                <when test=\\\"criterion.noValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.singleValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.betweenValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.listValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                    <foreach close=\\\")\\\" collection=\\\"criterion.value\\\" item=\\\"listItem\\\" open=\\\"(\\\" separator=\\\",\\\">\\n\" +\n            \"                                        #{listItem}\\n\" +\n            \"                                    </foreach>\\n\" +\n            \"                                </when>\\n\" +\n            \"                            </choose>\\n\" +\n            \"                        </foreach>\\n\" +\n            \"                    </trim>\\n\" +\n            \"                </if>\\n\" +\n            \"            </foreach>\\n\" +\n            \"        </where>\\n\" +\n            \"    </sql>\\n\" +\n            \"\\n\" +\n            \"    <!-- 1.根据条件查询列表 -->\\n\" +\n            \"    <select id=\\\"selectByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"        <if test=\\\"distinct\\\">\\n\" +\n            \"            DISTINCT\\n\" +\n            \"        </if>\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"orderByClause != null\\\">\\n\" +\n            \"            ORDER BY ${orderByClause}\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"limit != null\\\">\\n\" +\n            \"            LIMIT ${limit}\\n\" +\n            \"        </if>\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 2.批量更新, 根据主键更新非null字段 -->\\n\" +\n            \"    <update id=\\\"updateBatchByPrimaryKeySelective\\\" parameterType=\\\"java.util.List\\\">\\n\" +\n            \"        <foreach collection=\\\"list\\\" open=\\\"\\\" close=\\\"\\\" separator=\\\";\\\" item=\\\"item\\\">\\n\" +\n            \"            UPDATE `@mo_table_name@`\\n\" +\n            \"            <set>\\n\" +\n            \"@BatchUpdateNonNullFieldByID@\\n\" +\n            \"            </set>\\n\" +\n            \"            WHERE `id` = #{item.id}\\n\" +\n            \"        </foreach>\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 3.根据条件更新非null字段 -->\\n\" +\n            \"    <update id=\\\"updateByExampleSelective\\\" parameterType=\\\"map\\\">\\n\" +\n            \"        UPDATE `@mo_table_name@`\\n\" +\n            \"        <set>\\n\" +\n            \"@UpdateNonNullFieldByExample@\\n\" +\n            \"        </set>\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Update_By_Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 4.根据条件删除记录 -->\\n\" +\n            \"    <delete id=\\\"deleteByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\">\\n\" +\n            \"        DELETE FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </delete>\\n\" +\n            \"\\n\" +\n            \"    <!-- 5.根据条件统计记录 -->\\n\" +\n            \"    <select id=\\\"countByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"            COUNT(*)\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 6.增加单条记录, 返回主键 -->\\n\" +\n            \"    <insert id=\\\"insertWithId\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@` (\\n\" +\n            \"@BaseColumnList@\\n\" +\n            \"        )\\n\" +\n            \"        values (\\n\" +\n            \"@InsertField@\\n\" +\n            \"        )\\n\" +\n            \"    </insert>\\n\" +\n            \"\\n\" +\n            \"    <!-- 7.批量增加记录, 返回主键 -->\\n\" +\n            \"    <insert id=\\\"insertBatchWithId\\\" parameterType=\\\"java.util.List\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@` (\\n\" +\n            \"@BaseColumnList@\\n\" +\n            \"        )\\n\" +\n            \"        VALUES\\n\" +\n            \"        <foreach collection=\\\"list\\\" item=\\\"item\\\" separator=\\\",\\\">\\n\" +\n            \"@BatchInsertField@\\n\" +\n            \"        </foreach>\\n\" +\n            \"    </insert>\\n\" +\n            \"\\n\" +\n            \"    <!-- 8.@MoName@列表查询 -->\\n\" +\n            \"    <select id=\\\"query@MoName@MoList\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\"  resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        WHERE 1 = 1\\n\" +\n            \"@MoListQuery@\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 9.根据ID查询对象 -->\\n\" +\n            \"    <select id=\\\"selectByPrimaryKey\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        WHERE `id` = #{id}\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 10.根据主键只更新非null字段 -->\\n\" +\n            \"    <update id=\\\"updateByPrimaryKeySelective\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        UPDATE `@mo_table_name@`\\n\" +\n            \"        <set>\\n\" +\n            \"@UpdateNonNullFieldByID@\\n\" +\n            \"        </set>\\n\" +\n            \"        WHERE `id` = #{id}\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 11.根据ID删除记录 -->\\n\" +\n            \"    <delete id=\\\"deleteByPrimaryKey\\\">\\n\" +\n            \"        DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\\n\" +\n            \"    </delete>\\n\" +\n            \"\\n\" +\n            \"    <!-- 12.根据条件查询单个对象 -->\\n\" +\n            \"    <select id=\\\"selectOneByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"        <if test=\\\"distinct\\\">\\n\" +\n            \"            DISTINCT\\n\" +\n            \"        </if>\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"orderByClause != null\\\">\\n\" +\n            \"            ORDER BY ${orderByClause}\\n\" +\n            \"        </if>\\n\" +\n            \"        LIMIT 1\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 13.增加单条非空字段记录, 返回主键 -->\\n\" +\n            \"    <insert id=\\\"insertSelectiveWithId\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@`\\n\" +\n            \"        <trim prefix=\\\"(\\\" suffix=\\\")\\\" suffixOverrides=\\\",\\\">\\n\" +\n            \"@NonNullColumnList@\\n\" +\n            \"        </trim>\\n\" +\n            \"        <trim prefix=\\\"VALUES (\\\" suffix=\\\")\\\" suffixOverrides=\\\",\\\">\\n\" +\n            \"@NonNullInsertField@\\n\" +\n            \"        </trim>\\n\" +\n            \"    </insert>\\n\" +\n            \"</mapper>\");\n\n    /**\n     * Service implement template string\n     */\n    public static StringBuilder ZN_TEMPLATE_HANDLER = new StringBuilder(\"package @handlerPackage@;\\n\" +\n            \"\\n\" +\n            \"import @mapperPackage@.@MoName@Mapper;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import com.github.pagehelper.PageHelper;\\n\" +\n            \"import org.springframework.stereotype.Service;\\n\" +\n            \"import lombok.extern.slf4j.Slf4j;\\n\" +\n            \"\\n\" +\n            \"import javax.annotation.Resource;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"import java.util.Objects;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo对应的Handler\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Service\\n\" +\n            \"@Slf4j\\n\" +\n            \"public class @MoName@Handler {\\n\" +\n            \"\\n\" +\n            \"    @Resource\\n\" +\n            \"    private @MoName@Mapper @uncapitallizeMoName@Mapper;\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 插入单条记录\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 批量插入\\n\" +\n            \"     * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 查询列表, 如果携带分页参数则返回分页后的列表\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @param pageParams 可选分页参数\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\\n\" +\n            \"        if (Objects.nonNull(pageParams) && pageParams.length > 0) {\\n\" +\n            \"            int pageNum = pageParams[0];\\n\" +\n            \"            int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\\n\" +\n            \"            PageHelper.startPage(pageNum, pageSize);\\n\" +\n            \"        }\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据id更新非null字段\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 批量根据id更新非null字段\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据id物理删除\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public <T extends Number> int delete(T id) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * 根据id查询单条记录\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public <T extends Number> @MoName@Mo selectByPrimaryKey(T id) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"}\");\n\n    /**\n     * Controller template string\n     */\n    public static StringBuilder ZN_TEMPLATE_CONTROLLER = new StringBuilder(\"package @controllerPackage@;\\n\" +\n            \"\\n\" +\n            \"import @handlerPackage@.@MoName@Handler;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import @swaggerMoPackage@.@MoName@Vo;\\n\" +\n            \"import com.alibaba.fastjson.JSONObject;\\n\" +\n            \"import com.github.pagehelper.PageInfo;\\n\" +\n            \"import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\\n\" +\n            \"import com.github.xiaoymin.knife4j.annotations.ApiSort;\\n\" +\n            \"import io.swagger.annotations.Api;\\n\" +\n            \"import io.swagger.annotations.ApiOperation;\\n\" +\n            \"import lombok.extern.slf4j.Slf4j;\\n\" +\n            \"import org.springframework.web.bind.annotation.PostMapping;\\n\" +\n            \"import org.springframework.web.bind.annotation.RequestBody;\\n\" +\n            \"import org.springframework.web.bind.annotation.RestController;\\n\" +\n            \"\\n\" +\n            \"import javax.annotation.Resource;\\n\" +\n            \"import javax.validation.Valid;\\n\" +\n            \"import javax.validation.constraints.NotEmpty;\\n\" +\n            \"import java.util.ArrayList;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo控制器\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@RestController\\n\" +\n            \"@Api(tags = {\\\"@MoName@Mo模块接口\\\"})\\n\" +\n            \"@ApiSort(0)\\n\" +\n            \"@Slf4j\\n\" +\n            \"public class @MoName@Controller {\\n\" +\n            \"\\n\" +\n            \"    @Resource\\n\" +\n            \"    private @MoName@Handler @uncapitallizeMoName@Handler;\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 1)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo新增记录\\\")\\n\" +\n            \"    public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // 转换数据\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\\n\" +\n            \"        return @uncapitallizeMoName@Mo.getId();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 2)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo批量新增\\\")\\n\" +\n            \"    public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\\n\" +\n            \"        List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\\n\" +\n            \"        for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\\n\" +\n            \"            @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\\n\" +\n            \"        }\\n\" +\n            \"        return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 3)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo列表查询\\\")\\n\" +\n            \"    public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // 转换数据\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 4)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo分页查询\\\")\\n\" +\n            \"    public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // 转换数据\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\\n\" +\n            \"        return PageInfo.of(result@MoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 5)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo修改记录\\\")\\n\" +\n            \"    public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // 转换数据\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 5)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo批量修改记录\\\")\\n\" +\n            \"    public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\\n\" +\n            \"        // 转换数据\\n\" +\n            \"        List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\\n\" +\n            \"        @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\\n\" +\n            \"        return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 6)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo删除记录\\\")\\n\" +\n            \"    public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"}\\n\");\n    /**\n     * Mo template string\n     */\n    public static StringBuilder TEMPLATE_MO = new StringBuilder(\"package @moPackage@;\\n\" +\n            \"\\n\" +\n            \"import lombok.AllArgsConstructor;\\n\" +\n            \"import lombok.Data;\\n\" +\n            \"import lombok.NoArgsConstructor;\\n\" +\n            \"import lombok.experimental.Accessors;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Data\\n\" +\n            \"@NoArgsConstructor\\n\" +\n            \"@AllArgsConstructor\\n\" +\n            \"@Accessors(chain = true)\\n\" +\n            \"public class @MoName@Mo {\\n\" +\n            \"\\n\" +\n            \"@field@\\n\" +\n            \"\\n\" +\n            \"}\");\n    /**\n     * Swagger enhance VO template string\n     */\n    public static StringBuilder TEMPLATE_SWAGGER_VO = new StringBuilder(\"package @swaggerMoPackage@;\\n\" +\n            \"\\n\" +\n            \"import io.swagger.annotations.ApiModel;\\n\" +\n            \"import io.swagger.annotations.ApiModelProperty;\\n\" +\n            \"import lombok.AllArgsConstructor;\\n\" +\n            \"import lombok.Data;\\n\" +\n            \"import lombok.NoArgsConstructor;\\n\" +\n            \"import lombok.experimental.Accessors;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo with SwaggerApi Enhance Vo\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Data\\n\" +\n            \"@NoArgsConstructor\\n\" +\n            \"@AllArgsConstructor\\n\" +\n            \"@Accessors(chain = true)\\n\" +\n            \"@ApiModel\\n\" +\n            \"public class @MoName@Vo {\\n\" +\n            \"\\n\" +\n            \"@swaggerField@\\n\" +\n            \"\\n\" +\n            \"}\");\n    /**\n     * Sql template string\n     */\n    public static StringBuilder TEMPLATE_MO_SQL = new StringBuilder(\"\\n\" +\n            \"-- ----------------------------\\n\" +\n            \"-- D8ger-Sql-Auto-Generated\\n\" +\n            \"-- Table structure for `@mo_table_name@`\\n\" +\n            \"-- @author @d8Author@\\n\" +\n            \"-- ----------------------------\\n\" +\n            \"-- DROP TABLE IF EXISTS `@mo_table_name@`;\\n\" +\n            \"CREATE TABLE `@mo_table_name@`\\n\" +\n            \"(\\n\" +\n            \"@sql_column@\\n\" +\n            \")\\n\" +\n            \"    comment '@MoName@' charset = utf8mb4;\\n\");\n    /**\n     * Mapper template string\n     */\n    public static StringBuilder TEMPLATE_MAPPER = new StringBuilder(\"package @mapperPackage@;\\n\" +\n            \"\\n\" +\n            \"import @moExamplePackage@.@MoName@Example;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import org.apache.ibatis.annotations.Param;\\n\" +\n            \"import @MapperAnnotationPackage@;\\n\" +\n            \"\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo Database Mapper\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@MapperAnnotation@\\n\" +\n            \"public interface @MoName@Mapper {\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Query list by criteria, supporting all conditions for querying a single table\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Batch update non-null fields by ID for multi-records\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Update non-null fields by ID for a single record\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateByExampleSelective(@Param(\\\"record\\\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\\\"example\\\") @MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Delete a single record by condition\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Statistical records by query conditions\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return Number of records\\n\" +\n            \"     */\\n\" +\n            \"    int countByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Add a single record, and set the ID for the input Mo parameter\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Batch add records, and set the ID for the input MoList parameters\\n\" +\n            \"     * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * @MoName@ query list\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Query just one record by ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    <T extends Number> @MoName@Mo selectByPrimaryKey(T id);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Update non-null fields by ID for a single record\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Delete a record by ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    <T extends Number> int deleteByPrimaryKey(T id);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Query just one record by criteria, supporting all conditions for querying a single table\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Example\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Add a single record with nonNull field, and set the ID for the input Mo parameter\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\\n\" +\n            \"\\n\" +\n            \"}\");\n    /**\n     * Example template string\n     */\n    public static StringBuilder TEMPLATE_MO_EXAMPLE = new StringBuilder(\"package @moExamplePackage@;\\n\" +\n            \"\\n\" +\n            \"import java.math.BigDecimal;\\n\" +\n            \"import java.time.LocalDateTime;\\n\" +\n            \"import java.util.ArrayList;\\n\" +\n            \"import java.util.Date;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Mo with multi-conditions object, Example\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"public class @MoName@Example {\\n\" +\n            \"\\n\" +\n            \"    protected String orderByClause;\\n\" +\n            \"\\n\" +\n            \"    protected Integer limit;\\n\" +\n            \"\\n\" +\n            \"    protected boolean distinct;\\n\" +\n            \"\\n\" +\n            \"    protected List<Criteria> conditionCriteria;\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example() {\\n\" +\n            \"        conditionCriteria = new ArrayList<>();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andOrderByClause(String orderByClause) {\\n\" +\n            \"        this.orderByClause = orderByClause;\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public String getOrderByClause() {\\n\" +\n            \"        return orderByClause;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andLimit(Integer limit) {\\n\" +\n            \"        if (limit != null && limit > 0) {\\n\" +\n            \"            this.limit = limit;\\n\" +\n            \"        }\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Integer getLimit() {\\n\" +\n            \"        return limit;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public @MoName@Example andDistinct(boolean distinct) {\\n\" +\n            \"        this.distinct = distinct;\\n\" +\n            \"        return this;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public boolean isDistinct() {\\n\" +\n            \"        return distinct;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public List<Criteria> getConditionCriteria() {\\n\" +\n            \"        return conditionCriteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public void or(Criteria criteria) {\\n\" +\n            \"        conditionCriteria.add(criteria);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Criteria or() {\\n\" +\n            \"        Criteria criteria = createCriteriaInternal();\\n\" +\n            \"        conditionCriteria.add(criteria);\\n\" +\n            \"        return criteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public Criteria createCriteria() {\\n\" +\n            \"        Criteria criteria = createCriteriaInternal();\\n\" +\n            \"        if (conditionCriteria.size() == 0) {\\n\" +\n            \"            conditionCriteria.add(criteria);\\n\" +\n            \"        }\\n\" +\n            \"        return criteria;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    protected Criteria createCriteriaInternal() {\\n\" +\n            \"        return new Criteria();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public void clear() {\\n\" +\n            \"        conditionCriteria.clear();\\n\" +\n            \"        orderByClause = null;\\n\" +\n            \"        distinct = false;\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    protected abstract static class GeneratedCriteria {\\n\" +\n            \"        protected List<Criterion> criteria;\\n\" +\n            \"\\n\" +\n            \"        protected GeneratedCriteria() {\\n\" +\n            \"            super();\\n\" +\n            \"            criteria = new ArrayList<>();\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isValid() {\\n\" +\n            \"            return criteria.size() > 0;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public List<Criterion> getAllCriteria() {\\n\" +\n            \"            return criteria;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public List<Criterion> getCriteria() {\\n\" +\n            \"            return criteria;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition) {\\n\" +\n            \"            if (condition == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Value for condition cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition, Object value, String property) {\\n\" +\n            \"            if (value == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Value for \\\" + property + \\\" cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition, value));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected void addCriterion(String condition, Object value1, Object value2, String property) {\\n\" +\n            \"            if (value1 == null || value2 == null) {\\n\" +\n            \"                throw new RuntimeException(\\\"Between values for \\\" + property + \\\" cannot be null\\\");\\n\" +\n            \"            }\\n\" +\n            \"            criteria.add(new Criterion(condition, value1, value2));\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"@ExampleDefinitionMethod@\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public static class Criteria extends GeneratedCriteria {\\n\" +\n            \"        protected Criteria() {\\n\" +\n            \"            super();\\n\" +\n            \"        }\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    public static class Criterion {\\n\" +\n            \"        private String condition;\\n\" +\n            \"\\n\" +\n            \"        private Object value;\\n\" +\n            \"\\n\" +\n            \"        private Object secondValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean noValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean singleValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean betweenValue;\\n\" +\n            \"\\n\" +\n            \"        private boolean listValue;\\n\" +\n            \"\\n\" +\n            \"        private String typeHandler;\\n\" +\n            \"\\n\" +\n            \"        public String getCondition() {\\n\" +\n            \"            return condition;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public Object getValue() {\\n\" +\n            \"            return value;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public Object getSecondValue() {\\n\" +\n            \"            return secondValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isNoValue() {\\n\" +\n            \"            return noValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isSingleValue() {\\n\" +\n            \"            return singleValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isBetweenValue() {\\n\" +\n            \"            return betweenValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public boolean isListValue() {\\n\" +\n            \"            return listValue;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        public String getTypeHandler() {\\n\" +\n            \"            return typeHandler;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.typeHandler = null;\\n\" +\n            \"            this.noValue = true;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, String typeHandler) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.value = value;\\n\" +\n            \"            this.typeHandler = typeHandler;\\n\" +\n            \"            if (value instanceof List<?>) {\\n\" +\n            \"                this.listValue = true;\\n\" +\n            \"            } else {\\n\" +\n            \"                this.singleValue = true;\\n\" +\n            \"            }\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value) {\\n\" +\n            \"            this(condition, value, null);\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\\n\" +\n            \"            super();\\n\" +\n            \"            this.condition = condition;\\n\" +\n            \"            this.value = value;\\n\" +\n            \"            this.secondValue = secondValue;\\n\" +\n            \"            this.typeHandler = typeHandler;\\n\" +\n            \"            this.betweenValue = true;\\n\" +\n            \"        }\\n\" +\n            \"\\n\" +\n            \"        protected Criterion(String condition, Object value, Object secondValue) {\\n\" +\n            \"            this(condition, value, secondValue, null);\\n\" +\n            \"        }\\n\" +\n            \"    }\\n\" +\n            \"}\");\n    /**\n     * Sql xml template string\n     */\n    public static StringBuilder TEMPLATE_MAPPER_XML = new StringBuilder(\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n\" +\n            \"<!DOCTYPE mapper PUBLIC \\\"-//mybatis.org//DTD Mapper 3.0//EN\\\" \\\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\\\">\\n\" +\n            \"<mapper namespace=\\\"@mapperPackage@.@MoName@Mapper\\\">\\n\" +\n            \"\\n\" +\n            \"    <!-- Conditions during query operation -->\\n\" +\n            \"    <sql id=\\\"Example_Where_Clause\\\">\\n\" +\n            \"        <where>\\n\" +\n            \"            <foreach collection=\\\"conditionCriteria\\\" item=\\\"criteria\\\" separator=\\\"or\\\">\\n\" +\n            \"                <if test=\\\"criteria.valid\\\">\\n\" +\n            \"                    <trim prefix=\\\"(\\\" prefixOverrides=\\\"and\\\" suffix=\\\")\\\">\\n\" +\n            \"                        <foreach collection=\\\"criteria.criteria\\\" item=\\\"criterion\\\">\\n\" +\n            \"                            <choose>\\n\" +\n            \"                                <when test=\\\"criterion.noValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.singleValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.betweenValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.listValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                    <foreach close=\\\")\\\" collection=\\\"criterion.value\\\" item=\\\"listItem\\\" open=\\\"(\\\" separator=\\\",\\\">\\n\" +\n            \"                                        #{listItem}\\n\" +\n            \"                                    </foreach>\\n\" +\n            \"                                </when>\\n\" +\n            \"                            </choose>\\n\" +\n            \"                        </foreach>\\n\" +\n            \"                    </trim>\\n\" +\n            \"                </if>\\n\" +\n            \"            </foreach>\\n\" +\n            \"        </where>\\n\" +\n            \"    </sql>\\n\" +\n            \"\\n\" +\n            \"    <!-- Conditions during update operation -->\\n\" +\n            \"    <sql id=\\\"Update_By_Example_Where_Clause\\\">\\n\" +\n            \"        <where>\\n\" +\n            \"            <foreach collection=\\\"example.conditionCriteria\\\" item=\\\"criteria\\\" separator=\\\"or\\\">\\n\" +\n            \"                <if test=\\\"criteria.valid\\\">\\n\" +\n            \"                    <trim prefix=\\\"(\\\" prefixOverrides=\\\"and\\\" suffix=\\\")\\\">\\n\" +\n            \"                        <foreach collection=\\\"criteria.criteria\\\" item=\\\"criterion\\\">\\n\" +\n            \"                            <choose>\\n\" +\n            \"                                <when test=\\\"criterion.noValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.singleValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.betweenValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\\n\" +\n            \"                                </when>\\n\" +\n            \"                                <when test=\\\"criterion.listValue\\\">\\n\" +\n            \"                                    AND ${criterion.condition}\\n\" +\n            \"                                    <foreach close=\\\")\\\" collection=\\\"criterion.value\\\" item=\\\"listItem\\\" open=\\\"(\\\" separator=\\\",\\\">\\n\" +\n            \"                                        #{listItem}\\n\" +\n            \"                                    </foreach>\\n\" +\n            \"                                </when>\\n\" +\n            \"                            </choose>\\n\" +\n            \"                        </foreach>\\n\" +\n            \"                    </trim>\\n\" +\n            \"                </if>\\n\" +\n            \"            </foreach>\\n\" +\n            \"        </where>\\n\" +\n            \"    </sql>\\n\" +\n            \"\\n\" +\n            \"    <!-- 1.Query list by criteria -->\\n\" +\n            \"    <select id=\\\"selectByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"        <if test=\\\"distinct\\\">\\n\" +\n            \"            DISTINCT\\n\" +\n            \"        </if>\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"orderByClause != null\\\">\\n\" +\n            \"            ORDER BY ${orderByClause}\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"limit != null\\\">\\n\" +\n            \"            LIMIT ${limit}\\n\" +\n            \"        </if>\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 2.Batch update non-null fields by ID for multi-records -->\\n\" +\n            \"    <update id=\\\"updateBatchByPrimaryKeySelective\\\" parameterType=\\\"java.util.List\\\">\\n\" +\n            \"        <foreach collection=\\\"list\\\" open=\\\"\\\" close=\\\"\\\" separator=\\\";\\\" item=\\\"item\\\">\\n\" +\n            \"            UPDATE `@mo_table_name@`\\n\" +\n            \"            <set>\\n\" +\n            \"@BatchUpdateNonNullFieldByID@\\n\" +\n            \"            </set>\\n\" +\n            \"            WHERE `id` = #{item.id}\\n\" +\n            \"        </foreach>\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 3.Update non-null fields by ID for a single record -->\\n\" +\n            \"    <update id=\\\"updateByExampleSelective\\\" parameterType=\\\"map\\\">\\n\" +\n            \"        UPDATE `@mo_table_name@`\\n\" +\n            \"        <set>\\n\" +\n            \"@UpdateNonNullFieldByExample@\\n\" +\n            \"        </set>\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Update_By_Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 4.Delete a single record by condition -->\\n\" +\n            \"    <delete id=\\\"deleteByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\">\\n\" +\n            \"        DELETE FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </delete>\\n\" +\n            \"\\n\" +\n            \"    <!-- 5.Statistical records by query conditions -->\\n\" +\n            \"    <select id=\\\"countByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"            COUNT(*)\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 6.Add a single record, and return the ID -->\\n\" +\n            \"    <insert id=\\\"insertWithId\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@` (\\n\" +\n            \"@BaseColumnList@\\n\" +\n            \"        )\\n\" +\n            \"        values (\\n\" +\n            \"@InsertField@\\n\" +\n            \"        )\\n\" +\n            \"    </insert>\\n\" +\n            \"\\n\" +\n            \"    <!-- 7.Batch add records, and return the IDs -->\\n\" +\n            \"    <insert id=\\\"insertBatchWithId\\\" parameterType=\\\"java.util.List\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@` (\\n\" +\n            \"@BaseColumnList@\\n\" +\n            \"        )\\n\" +\n            \"        VALUES\\n\" +\n            \"        <foreach collection=\\\"list\\\" item=\\\"item\\\" separator=\\\",\\\">\\n\" +\n            \"@BatchInsertField@\\n\" +\n            \"        </foreach>\\n\" +\n            \"    </insert>\\n\" +\n            \"\\n\" +\n            \"    <!-- 8.@MoName@ query list -->\\n\" +\n            \"    <select id=\\\"query@MoName@MoList\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\"  resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        WHERE 1 = 1\\n\" +\n            \"@MoListQuery@\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 9.Query just one record by ID -->\\n\" +\n            \"    <select id=\\\"selectByPrimaryKey\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        WHERE `id` = #{id}\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 10.Update non-null fields by ID for a single record -->\\n\" +\n            \"    <update id=\\\"updateByPrimaryKeySelective\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        UPDATE `@mo_table_name@`\\n\" +\n            \"        <set>\\n\" +\n            \"@UpdateNonNullFieldByID@\\n\" +\n            \"        </set>\\n\" +\n            \"        WHERE `id` = #{id}\\n\" +\n            \"    </update>\\n\" +\n            \"\\n\" +\n            \"    <!-- 11.Delete a record by ID -->\\n\" +\n            \"    <delete id=\\\"deleteByPrimaryKey\\\">\\n\" +\n            \"        DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\\n\" +\n            \"    </delete>\\n\" +\n            \"\\n\" +\n            \"    <!-- 12.Query just one record by criteria -->\\n\" +\n            \"    <select id=\\\"selectOneByExample\\\" parameterType=\\\"@moExamplePackage@.@MoName@Example\\\" resultType=\\\"@moPackage@.@MoName@Mo\\\">\\n\" +\n            \"        SELECT\\n\" +\n            \"        <if test=\\\"distinct\\\">\\n\" +\n            \"            DISTINCT\\n\" +\n            \"        </if>\\n\" +\n            \"@SelectBaseColumnList@\\n\" +\n            \"        FROM `@mo_table_name@`\\n\" +\n            \"        <if test=\\\"_parameter != null\\\">\\n\" +\n            \"            <include refid=\\\"Example_Where_Clause\\\"/>\\n\" +\n            \"        </if>\\n\" +\n            \"        <if test=\\\"orderByClause != null\\\">\\n\" +\n            \"            ORDER BY ${orderByClause}\\n\" +\n            \"        </if>\\n\" +\n            \"        LIMIT 1\\n\" +\n            \"    </select>\\n\" +\n            \"\\n\" +\n            \"    <!-- 13.Add a single record with nonNull field, and return the ID -->\\n\" +\n            \"    <insert id=\\\"insertSelectiveWithId\\\" parameterType=\\\"@moPackage@.@MoName@Mo\\\" useGeneratedKeys=\\\"true\\\" keyProperty=\\\"id\\\">\\n\" +\n            \"        INSERT INTO `@mo_table_name@`\\n\" +\n            \"        <trim prefix=\\\"(\\\" suffix=\\\")\\\" suffixOverrides=\\\",\\\">\\n\" +\n            \"@NonNullColumnList@\\n\" +\n            \"        </trim>\\n\" +\n            \"        <trim prefix=\\\"VALUES (\\\" suffix=\\\")\\\" suffixOverrides=\\\",\\\">\\n\" +\n            \"@NonNullInsertField@\\n\" +\n            \"        </trim>\\n\" +\n            \"    </insert>\\n\" +\n            \"</mapper>\");\n\n    /**\n     * Service implement template string\n     */\n    public static StringBuilder TEMPLATE_HANDLER = new StringBuilder(\"package @handlerPackage@;\\n\" +\n            \"\\n\" +\n            \"import @mapperPackage@.@MoName@Mapper;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import com.github.pagehelper.PageHelper;\\n\" +\n            \"import org.springframework.stereotype.Service;\\n\" +\n            \"import lombok.extern.slf4j.Slf4j;\\n\" +\n            \"\\n\" +\n            \"import javax.annotation.Resource;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"import java.util.Objects;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@Handler\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@Service\\n\" +\n            \"@Slf4j\\n\" +\n            \"public class @MoName@Handler {\\n\" +\n            \"\\n\" +\n            \"    @Resource\\n\" +\n            \"    private @MoName@Mapper @uncapitallizeMoName@Mapper;\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Insert a record\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Batch insert records\\n\" +\n            \"     * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Query list, if the paging parameter is carried, return the list after paging\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @param pageParams Optional paging parameters\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\\n\" +\n            \"        if (Objects.nonNull(pageParams) && pageParams.length > 0) {\\n\" +\n            \"            int pageNum = pageParams[0];\\n\" +\n            \"            int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\\n\" +\n            \"            PageHelper.startPage(pageNum, pageSize);\\n\" +\n            \"        }\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Update non-null fields by ID for a single record\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@Mo\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Batch Update non-nulls field by ID for multi-records\\n\" +\n            \"     *\\n\" +\n            \"     * @param @uncapitallizeMoName@MoList\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Delete a record by ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public <T extends Number> int delete(T id) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    /**\\n\" +\n            \"     * Select a record by ID\\n\" +\n            \"     *\\n\" +\n            \"     * @param id\\n\" +\n            \"     * @return\\n\" +\n            \"     */\\n\" +\n            \"    public <T extends Number> @MoName@Mo selectByPrimaryKey(T id) {\\n\" +\n            \"        return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"}\");\n    /**\n     * Controller template string\n     */\n    public static StringBuilder TEMPLATE_CONTROLLER = new StringBuilder(\"package @controllerPackage@;\\n\" +\n            \"\\n\" +\n            \"import @handlerPackage@.@MoName@Handler;\\n\" +\n            \"import @moPackage@.@MoName@Mo;\\n\" +\n            \"import @swaggerMoPackage@.@MoName@Vo;\\n\" +\n            \"import com.alibaba.fastjson.JSONObject;\\n\" +\n            \"import com.github.pagehelper.PageInfo;\\n\" +\n            \"import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\\n\" +\n            \"import com.github.xiaoymin.knife4j.annotations.ApiSort;\\n\" +\n            \"import io.swagger.annotations.Api;\\n\" +\n            \"import io.swagger.annotations.ApiOperation;\\n\" +\n            \"import lombok.extern.slf4j.Slf4j;\\n\" +\n            \"import org.springframework.web.bind.annotation.PostMapping;\\n\" +\n            \"import org.springframework.web.bind.annotation.RequestBody;\\n\" +\n            \"import org.springframework.web.bind.annotation.RestController;\\n\" +\n            \"\\n\" +\n            \"import javax.annotation.Resource;\\n\" +\n            \"import javax.validation.Valid;\\n\" +\n            \"import javax.validation.constraints.NotEmpty;\\n\" +\n            \"import java.util.ArrayList;\\n\" +\n            \"import java.util.List;\\n\" +\n            \"\\n\" +\n            \"/**\\n\" +\n            \" * @MoName@MoController\\n\" +\n            \" *\\n\" +\n            \" * @author @d8Author@\\n\" +\n            \" */\\n\" +\n            \"@RestController\\n\" +\n            \"@Api(tags = {\\\"@MoName@Mo-ModuleAPI\\\"})\\n\" +\n            \"@ApiSort(0)\\n\" +\n            \"@Slf4j\\n\" +\n            \"public class @MoName@Controller {\\n\" +\n            \"\\n\" +\n            \"    @Resource\\n\" +\n            \"    private @MoName@Handler @uncapitallizeMoName@Handler;\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 1)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-AddRecord\\\")\\n\" +\n            \"    public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // convert Vo to Mo\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\\n\" +\n            \"        return @uncapitallizeMoName@Mo.getId();\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 2)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-BatchAddRecords\\\")\\n\" +\n            \"    public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\\n\" +\n            \"        List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\\n\" +\n            \"        for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\\n\" +\n            \"            @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\\n\" +\n            \"        }\\n\" +\n            \"        return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 3)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-QueryList\\\")\\n\" +\n            \"    public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // convert Vo to Mo\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 4)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-QueryListWithPaging\\\")\\n\" +\n            \"    public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // convert Vo to Mo\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\\n\" +\n            \"        return PageInfo.of(result@MoName@MoList);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 5)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-UpdateRecord\\\")\\n\" +\n            \"    public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        // convert Vo to Mo\\n\" +\n            \"        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\\n\" +\n            \"        return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 5)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-BatchUpdateRecords\\\")\\n\" +\n            \"    public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\\n\" +\n            \"        // convert Vo to Mo\\n\" +\n            \"        List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\\n\" +\n            \"        @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\\n\" +\n            \"        return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"    @PostMapping(value = \\\"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\\\")\\n\" +\n            \"    @ApiOperationSupport(order = 6)\\n\" +\n            \"    @ApiOperation(value = \\\"@MoName@Mo-DeleteRecord\\\")\\n\" +\n            \"    public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\\n\" +\n            \"        return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\\n\" +\n            \"    }\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"}\\n\");\n    /**\n     * Config template string\n     */\n    public static String TEMPLATE_D8GER = \"# The default author called 'D8ger', but it's highly recommended to modify\\n\" +\n            \"author=D8ger\\n\" +\n            \"\\n\" +\n            \"#### Basic generate, support two item configs such as:\\n\" +\n            \"#### autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\\n\" +\n            \"#### ATTENTION: if you config directory path, you should make sure it exists first\\n\" +\n            \"#### WARNING: if you config error, the auto code file will put into the origin directory named 'D8AutoCode'\\n\" +\n            \"#### THEN plugin will create Mo.java file\\n\" +\n            \"#### AND put the file into 'com.xyz.caofancpu.d8ger.test.Mo' directory\\n\" +\n            \"#### UNDER current project source directory which include '/src/main/java'\\n\" +\n            \"autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\\n\" +\n            \"autoCreateMapper=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper\\n\" +\n            \"autoCreateExample=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper/Example\\n\" +\n            \"autoCreateXML=true, /src/main/resources/mybatis\\n\" +\n            \"autoCreateDefinitionSQL=true, /doc\\n\" +\n            \"\\n\" +\n            \"#### Enhance generate, also support two item configs, please refer Basic generate\\n\" +\n            \"autoCreateSwaggerMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Vo\\n\" +\n            \"autoCreateHandler=true, /src/main/java/com/xyz/caofancpu/d8ger/test/handler\\n\" +\n            \"autoCreateController=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Controller\\n\" +\n            \"\\n\" +\n            \"#### Other normal binary config\\n\" +\n            \"autoFormatStyle=true\\n\" +\n            \"\\n\" +\n            \"#### Api path prefix\\n\" +\n            \"# apiUrlPrefix=/D8ger\\n\" +\n            \"\\n\" +\n            \"#### auto generating create_time and update_time SQL column definition\\n\" +\n            \"autoDetectSQLTimeColumn=true\\n\" +\n            \"\\n\" +\n            \"#### if true then moMapper with annotation @Mapper, otherwise, with annotation @Repository\\n\" +\n            \"mapperBatterThenRepository=true\\n\" +\n            \"\\n\" +\n            \"#### Language just for EN(English) and ZN(Chinese Simplified)\\n\" +\n            \"# locale=ZN\\n\";\n\n    public static String TEMPLATE_REGEX = \"0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions\\n\" +\n            \"Usage, static pattern can improve performance in regex searching:\\n\" +\n            \"    public static final Pattern XXX_REGEX = Pattern.compile(\\\"...Regex string...\\\");\\n\" +\n            \"\\n\" +\n            \"1.Whitespace Regex\\n\" +\n            \"((?:\\\\s)+)\\n\" +\n            \"\\n\" +\n            \"2.One or more newlines Regex\\n\" +\n            \"(?:\\\\\\\\n|(?:\\\\\\\\r\\\\\\\\n))+\\n\" +\n            \"\\n\" +\n            \"3.Phone validate Regex\\n\" +\n            \"^1[0-9]{10}$\\n\" +\n            \"\\n\" +\n            \"4.Email validate Regex\\n\" +\n            \"^([a-z0-9A-Z]+[-|\\\\\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\\\\\.)+[a-zA-Z]{2,}$\\n\" +\n            \"\\n\" +\n            \"5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species\\n\" +\n            \"^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\\\\\W_]+$)(?![a-z0-9]+$)(?![a-z\\\\\\\\W_]+$)(?![0-9\\\\\\\\W_]+$)[a-zA-Z0-9\\\\\\\\W_]{8,30}$\\n\" +\n            \"\\n\" +\n            \"6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital]\\n\" +\n            \"(?:position)(?:\\\\\\\\s)*(?:\\\\\\\\=)(?:\\\\\\\\s)*(?:\\\\\\\\d)*\\n\" +\n            \"\\n\" +\n            \"7.No '_' and begin with [A-Z] in word Regex\\n\" +\n            \"^(?!_)(?:[A-Z])[a-zA-Z0-9\\\\\\\\W]+$\\n\" +\n            \"\\n\" +\n            \"8.No upper case in word Regex\\n\" +\n            \"^(?![A-Z])[a-z0-9\\\\\\\\W_]+$\\n\" +\n            \"\\n\" +\n            \"9.No lower case in word Regex\\n\" +\n            \"^(?![a-z])[A-Z0-9\\\\\\\\W_]+$\\n\" +\n            \"\\n\" +\n            \"10.'www' Url detect Regex\\n\" +\n            \"^(?:http)(?:s)?(?:\\\\:\\\\/\\\\/)(?:www\\\\.)?(?:[^\\\\ ]*)$\\n\" +\n            \"\\n\" +\n            \"11.IDEA Skills\\n\" +\n            \"- 11.1 For multi-lines, how to add some same fix characters?\\n\" +\n            \" ResearchRegex@   (?:\\\\n|(?:\\\\r\\\\n))+\\n\" +\n            \" ReplaceString@   ,\\\\r\\\\n\\n\" +\n            \"\\n\" +\n            \"- 11.2 For multi-lines, especially for SQL batch replacing, such as:\\n\" +\n            \"    - zcy_cf,  --> WE'RE(zcy_cf) AS zcy_cf,\\n\" +\n            \"    - cf_zcy   --> WE'RE(cf_zcy) AS cf_zcy\\n\" +\n            \"    - note: WE'RE is just a function\\n\" +\n            \" I.Clear the character ','\\n\" +\n            \"  ResearchRegex@   (?:,)+\\n\" +\n            \"  ReplaceString@   [EMPTY]\\n\" +\n            \" II.Batch replace\\n\" +\n            \"  ResearchRegex@   ((?:\\\\w+)+)\\n\" +\n            \"  ReplaceString@   WE'RE($0) AS $0,\\n\" +\n            \" III.Clear the rare character ',' at the last line\\n\" +\n            \"\\n\" +\n            \"- 11.3 For multi-lines, especially for SQL batch reduce-replacing, such as:\\n\" +\n            \"    - WE'RE(zcy_cf) AS zcy_cf,  --> zcy_cf,\\n\" +\n            \"    - WE'RE(cf_zcy) AS cf_zcy   --> cf_zcy\\n\" +\n            \"    - note: WE'RE is just a function\\n\" +\n            \" I.Handle prefix\\n\" +\n            \"  ResearchRegex@   (?:WE'RE\\\\()+\\n\" +\n            \"  ReplaceString@   [EMPTY]\\n\" +\n            \" II.Handle suffix\\n\" +\n            \"  ResearchRegex@   (?:\\\\))(?:[^\\\\,]*)\\n\" +\n            \"  ReplaceString@   [EMPTY]\\n\" +\n            \" III.Watch out whether need to clear the rare character ',' at the last line\\n\" +\n            \"\\n\" +\n            \"12. Cron Expression\\n\" +\n            \"每隔5秒执行一次:                  */5 * * * * ?\\n\" +\n            \"每隔5分钟执行一次:                0 */5 * * * ?\\n\" +\n            \"每天23点执行一次:                 0 0 23 * * ?\\n\" +\n            \"每天凌晨2点执行一次:               0 0 2 * * ?\\n\" +\n            \"每月2号凌晨4点执行一次：            0 0 2 4 * ?\\n\" +\n            \"每月最后一天23点执行一次：          0 0 23 L * ?\\n\" +\n            \"每周星期天凌晨2点实行一次：          0 0 2 ? * L\\n\" +\n            \"在26分、29分、33分执行一次：        0 26,29,33 * * * ?\\n\" +\n            \"每天的0点、22点、23点都执行一次：    0 0 0 0,22,23 * * ?\\n\" +\n            \"\\n\";\n\n    public static String TEMPLATE_OH_MY_ZSH = \"export ZSH=\\\"$HOME/.oh-my-zsh\\\"\\n\" +\n            \"export HOMEBREW_NO_AUTO_UPDATE=true\\n\" +\n            \"\\n\" +\n            \"ZSH_THEME=\\\"powerlevel9k/powerlevel9k\\\"\\n\" +\n            \"POWERLEVEL9K_MODE=\\\"nerdfont-complete\\\"\\n\" +\n            \"POWERLEVEL9K_PROMPT_ON_NEWLINE=true\\n\" +\n            \"POWERLEVEL9K_RPROMPT_ON_NEWLINE=false\\n\" +\n            \"POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon user dir_writable dir vcs)\\n\" +\n            \"POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time root_indicator background_jobs time disk_usage ram)\\n\" +\n            \"#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\\\"%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )\\\"\\n\" +\n            \"#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\\\"\\\"\\n\" +\n            \"#POWERLEVEL9K_USER_ICON=\\\"\\\\uF415\\\" # \\uF415\\n\" +\n            \"POWERLEVEL9K_ROOT_ICON=\\\"\\\\uF09C\\\"\\n\" +\n            \"#POWERLEVEL9K_SUDO_ICON=$'\\\\uF09C' # \\uF09C\\n\" +\n            \"POWERLEVEL9K_TIME_FORMAT=\\\"%D{%H:%M}\\\"\\n\" +\n            \"#POWERLEVEL9K_VCS_GIT_ICON='\\\\uF408 '\\n\" +\n            \"#POWERLEVEL9K_VCS_GIT_GITHUB_ICON='\\\\uF408 '\\n\" +\n            \"\\n\" +\n            \"ZSH_DISABLE_COMPFIX=true\\n\" +\n            \"#ENABLE_CORRECTION=\\\"true\\\"\\n\" +\n            \"DISABLE_CORRECTION=true\\n\" +\n            \"COMPLETION_WAITING_DOTS=true\\n\" +\n            \"\\n\" +\n            \"# 左侧栏目显示的要素（指定的关键字参考官网）\\n\" +\n            \"#POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon context dir vcs)\\n\" +\n            \"# 右侧栏目显示的要素\\n\" +\n            \"#POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs time virtualenv)\\n\" +\n            \"#新起一行显示命令 (推荐！极其方便）\\n\" +\n            \"#POWERLEVEL9K_PROMPT_ON_NEWLINE=true\\n\" +\n            \"#右侧状态栏与命令在同一行\\n\" +\n            \"#POWERLEVEL9K_RPROMPT_ON_NEWLINE=false\\n\" +\n            \"#缩短目录层级\\n\" +\n            \"#POWERLEVEL9K_SHORTEN_DIR_LENGTH=1\\n\" +\n            \"#缩短目录策略：隐藏上层目录中间的字\\n\" +\n            \"#POWERLEVEL9K_SHORTEN_STRATEGY=\\\"truncate_middle\\\"\\n\" +\n            \"#添加连接上下连接箭头更方便查看\\n\" +\n            \"#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\\\"↱\\\"\\n\" +\n            \"#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\\\"↳ \\\"\\n\" +\n            \"# 新的命令与上面的命令隔开一行\\n\" +\n            \"#POWERLEVEL9K_PROMPT_ADD_NEWLINE=true\\n\" +\n            \"# Git仓库状态的色彩指定\\n\" +\n            \"#POWERLEVEL9K_VCS_CLEAN_FOREGROUND='blue'\\n\" +\n            \"#POWERLEVEL9K_VCS_CLEAN_BACKGROUND='black'\\n\" +\n            \"#POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND='yellow'\\n\" +\n            \"#POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='black'\\n\" +\n            \"#POWERLEVEL9K_VCS_MODIFIED_FOREGROUND='red'\\n\" +\n            \"#POWERLEVEL9K_VCS_MODIFIED_BACKGROUND='black'\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"DISABLE_AUTO_UPDATE=\\\"true\\\"\\n\" +\n            \"# autojump   : 'j'历史目录\\n\" +\n            \"# cp         : 'cpv'带进度条的复制\\n\" +\n            \"# zsh_reload : 'src'快速重载.zshrc\\n\" +\n            \"# 快速编辑.zshrc: alias 'vrc=vim ~/.zshrc'\\n\" +\n            \"# 快速展示.zshrc: alias 'crc=cat ~/.zshrc'\\n\" +\n            \"# extract    : 'x'解压任何文件\\n\" +\n            \"plugins=(git autojump cp zsh_reload extract zsh-syntax-highlighting)\\n\" +\n            \"\\n\" +\n            \"export LC_ALL=en_US.UTF-8  \\n\" +\n            \"export LANG=en_US.UTF-8\\n\" +\n            \"\\n\" +\n            \"# Maven家目录\\n\" +\n            \"export M2_HOME=/usr/local/maven-3.6.1/apache-maven-3.6.1\\n\" +\n            \"alias mcf=\\\"/usr/local/maven-3.6.1/caofanCPU-apache-maven-3.6.1/bin/mvn\\\"\\n\" +\n            \"\\n\" +\n            \"# 查看java安装位置命令 /usr/libexec/java_home -V\\n\" +\n            \"export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home\\n\" +\n            \"export JRE_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre\\n\" +\n            \"export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH\\n\" +\n            \"export PATH=$M2_HOME/bin:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH\\n\" +\n            \"\\n\" +\n            \"# Python项目打包工具包\\n\" +\n            \"export TWINE_HOME=/Users/D8GER/Library/Python/3.7\\n\" +\n            \"export PATH=$PATH:$TWINE_HOME/bin\\n\" +\n            \"\\n\" +\n            \"export PATH=$PATH:$HOME/bin\\n\" +\n            \"export PATH=\\\"$PATH:/usr/local/python3/bin\\\"\\n\" +\n            \"\\n\" +\n            \"# thefuck插件\\n\" +\n            \"eval \\\"$(thefuck --alias)\\\"\\n\" +\n            \"\\n\" +\n            \"# 服务器\\n\" +\n            \"alias caofanCPU='sshpass -f PWD_DIR  ssh  xxxx@xx.xx.xx.xx'\\n\" +\n            \"alias caofanJumpAli='sshpass -f PWD_DIR  ssh  xx@xx.xx.xx.xx'\\n\" +\n            \"\\n\" +\n            \"function execute() {\\n\" +\n            \"    http --session=~/Desktop/ssoLogin/session-${1}.json --verify=no -v ${2} POST ${@:3}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function downLoadResponse() {\\n\" +\n            \"    echo \\\"执行命令内容: \\\\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\\\n\\\"\\n\" +\n            \"    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function downLoadExcel() {\\n\" +\n            \"    echo \\\"执行命令内容: \\\\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\\\"\\n\" +\n            \"    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function downloadD8ger() {\\n\" +\n            \"    echo \\\"执行命令内容: 并发下载文件\\\"\\n\" +\n            \"    for i in {1..30}\\n\" +\n            \"        do \\n\" +\n            \"            http --verify=no -v --download  GET  ${1} -o D8.zip\\n\" +\n            \"    done\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function show() {\\n\" +\n            \"    echo \\\"执行命令内容: \\\\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\\\\n\\\"\\n\" +\n            \"    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function searchPortOccupy(){\\n\" +\n            \"    lsof -i :${1}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function searchPID(){\\n\" +\n            \"    ps aux | grep ${1} | grep -v grep | awk '{print $2}'\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function killPID(){\\n\" +\n            \"    pid=`ps aux | grep ${1} | grep -v grep | awk '{print $2}'`\\n\" +\n            \"    if [ -n \\\"$pid\\\" ]; then\\n\" +\n            \"        kill -9 $pid\\n\" +\n            \"        sleep 1\\n\" +\n            \"    fi\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"# 环境\\n\" +\n            \"function xDev() {\\n\" +\n            \"    sshpass -f ENV_PIR.txt  ssh xx@xx.xx.xx.${1}  -t  'cd /work/www/d8ger.com/logs/; exec $SHELL'\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"# 环境普通模式\\n\" +\n            \"function xDevNormal(){\\n\" +\n            \"    sshpass -f ENV_PIR.txt  ssh xx@xx.xx.xx.${1}\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"# 不同环境\\n\" +\n            \"function backgroundENV() {\\n\" +\n            \"    env=${1}\\n\" +\n            \"    if [ -z \\\"$env\\\" ]; then\\n\" +\n            \"        echo \\\"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\\\"\\n\" +\n            \"        return\\n\" +\n            \"    fi\\n\" +\n            \"    domain=''\\n\" +\n            \"    if [ \\\"$env\\\" = '1' ]; then\\n\" +\n            \"        domain='https://1.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '2' ]; then\\n\" +\n            \"        domain='https://2.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '3' ]; then\\n\" +\n            \"        domain='https://3.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '4' ]; then\\n\" +\n            \"        domain='https://4.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '5' ]; then\\n\" +\n            \"        domain='https://5.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '6' ]; then\\n\" +\n            \"        domain='https://6.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '7' ]; then\\n\" +\n            \"        domain='https://7.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '8' ]; then\\n\" +\n            \"        domain='https://8.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '9' ]; then\\n\" +\n            \"        domain='https://9.d8ger.com'\\n\" +\n            \"    elif [ \\\"$env\\\" = '10' ]; then\\n\" +\n            \"        domain='https://ok.d8ger.com'\\n\" +\n            \"    fi\\n\" +\n            \"    # 判断\\n\" +\n            \"    if [ -z \\\"$domain\\\" ]; then\\n\" +\n            \"        echo \\\"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\\\"\\n\" +\n            \"        return\\n\" +\n            \"    fi\\n\" +\n            \"    echo \\\"德玛西亚, http -v --verify=no POST  ${domain}/ok/xx\\\"\\n\" +\n            \"    echo \\\"查询任务是否启动及是否完成: grep \\\\\\\"德玛西亚\\\\\\\" all.log | grep \\\\\\\"end\\\\\\\"\\\"\\n\" +\n            \"    http -v --verify=no POST  ${domain}/ok/xx\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function justDoIT(){\\n\" +\n            \"    SID=${1}\\n\" +\n            \"    if [ -z \\\"$SID\\\" ]; then\\n\" +\n            \"        echo \\\"非法的SID, 请检查\\\"\\n\" +\n            \"        return\\n\" +\n            \"    fi    \\n\" +\n            \"    url=\\\"https://1.d8ger.com/xx/yy/zz\\\"\\n\" +\n            \"    # 登录\\n\" +\n            \"    login-cookie -f ~/Desktop/ssoLogin/sso-on-admin.json -a 6 \\n\" +\n            \"    # 执行\\n\" +\n            \"    echo \\\"执行:\\\\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\\\\n\\\"\\n\" +\n            \"    # http多个参数不能放在一个字符串中, 用多个变量来区分解决\\n\" +\n            \"    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function cph(){\\n\" +\n            \"    echo \\\",------.   ,---.  ,----.   ,------.,------.\\\"\\n\" +\n            \"    echo \\\"|  .-.  \\\\\\\\ |  o  |'  .-./   |  .---'|  .--. '\\\"\\n\" +\n            \"    echo \\\"|  |  \\\\\\\\  :.'   '.|  | .---.|  \\\\`--, |  '--'.'\\\"\\n\" +\n            \"    echo \\\"|  '--'  /|  o  |'  '--'  ||  \\\\`---.|  |\\\\\\\\  \\\\\\\\\\\"\\n\" +\n            \"    echo \\\"\\\\`-------'  \\\\`---'  \\\\`------' \\\\`------'\\\\`--' '--'\\\"\\n\" +\n            \"    echo \\\"##### SCP命令 #####\\\"\\n\" +\n            \"    echo \\\"# -r 支持复制目录及其子文件\\\"\\n\" +\n            \"    echo \\\"- 本地文件传到远程服务器\\\"\\n\" +\n            \"    echo \\\"scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh  caofan@172.16.10.59:~/\\\"\\n\" +\n            \"    echo \\\"- 从远程服务器拉取文件\\\"\\n\" +\n            \"    echo \\\"scp caofan@172.16.10.59:~/HAHA.tmp /Users/D8GER/Desktop/ssoLogin/ZZ.xls\\\"\\n\" +\n            \"    echo \\\"- 无痕登录\\\"\\n\" +\n            \"    echo \\\"xD8scp || d8scp\\\"\\n\" +\n            \"    echo \\\"sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh  caofan@172.16.10.59:~/\\\"\\n\" +\n            \"    echo \\\"sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh  caofan@172.16.10.59:~/\\\"\\n\" +\n            \"    echo \\\"##### cpv #####, zsh的一个插件cp, 文件复制时展示进度条\\\"\\n\" +\n            \"    echo \\\"##### sudo cp #####, 普通复制\\\"\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function fkgrep(){\\n\" +\n            \"    echo \\\",------.,--. ,--. ,----.   ,------. ,------.,------.\\\"\\n\" +\n            \"    echo \\\"|  .---'|  .'   /'  .-./   |  .--. '|  .---'|  .--. '\\\"\\n\" +\n            \"    echo \\\"|  \\\\`--, |  .   ' |  | .---.|  '--'.'|  \\\\`--, |  '--' |\\\"\\n\" +\n            \"    echo \\\"|  |\\\\`   |  |\\\\\\\\   \\\\'  '--'  ||  |\\\\\\\\  \\\\\\\\ |  \\\\`---.|  | --'\\\"\\n\" +\n            \"    echo \\\"\\\\`--'    \\\\`--' '--' \\\\`------' \\\\`--' '--'\\\\`------'\\\\`--'\\\"\\n\" +\n            \"    echo \\\"\\\"\\n\" +\n            \"    echo \\\"grep -n '[a-zA-Z0-9]D8' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '[^a-zA-Z0-9]D9' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '^[a-z]' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '^[^a-z]' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '^$' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '\\\\.$' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n 'g.*d' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n 'go*d' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n 'o\\\\{2,3\\\\}' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -En 'God|The'  X.txt     grep -n 'god\\\\|The' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -En 'o+' X.txt           grep -n 'o\\\\+' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -n '\\\\.' X.txt            grep -En '\\\\.' X.txt\\\"\\n\" +\n            \"    echo \\\"grep -En '(oo)+' X.txt        grep -n '\\\\(oo\\\\)\\\\+' X.txt\\\"\\n\" +\n            \"    echo \\\"Search Today's log: ll -ah | grep \\\\\\\"[a-z_A-Z]\\\\+\\\\.log\\\\\\\"\\\"\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"function arthasHelp(){\\n\" +\n            \"    echo \\\"  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.\\\"\\n\" +\n            \"    echo \\\" /  O  \\\\\\\\ |  .--. ''--.  .--'|  '--'  | /  O  \\\\\\\\ '   .-'\\\"\\n\" +\n            \"    echo \\\"|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |\\\\`.  \\\\`-.\\\"\\n\" +\n            \"    echo \\\"|  | |  ||  |\\\\\\\\  \\\\\\\\    |  |   |  |  |  ||  | |  |.-'    |\\\"\\n\" +\n            \"    echo \\\"\\\\`--' \\\\`--'\\\\`--' '--'   \\\\`--'   \\\\`--'  \\\\`--'\\\\`--' \\\\`--'\\\\`-----'\\\"\\n\" +\n            \"    # `和\\\\ 为特殊字符, 必须使用\\\\转义\\n\" +\n            \"    echo \\\"\\\\n# 观察方法返回值\\\"\\n\" +\n            \"    echo \\\"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\\\\\"{params,returnObj}\\\\\\\" -x 2\\\"\\n\" +\n            \"    echo \\\"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\\\\\"{params,returnObj}\\\\\\\"\\\"\\n\" +\n            \"    echo \\\"# 观察方法入参, 对象层次限制2级\\\"\\n\" +\n            \"    echo \\\"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\\\\\"{params,returnObj}\\\\\\\" -x 2 -b\\\"\\n\" +\n            \"    echo \\\"# 持续记录3次接口调用\\\"\\n\" +\n            \"    echo \\\"tt -t -n 3 com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage\\\"\\n\" +\n            \"    echo \\\"# 展示记录接口调用的列表\\\"\\n\" +\n            \"    echo \\\"tt -l\\\"\\n\" +\n            \"    echo \\\"# 展示某个具体调用过程\\\"\\n\" +\n            \"    echo \\\"tt -i 1002\\\"\\n\" +\n            \"    echo \\\"# 重复某个具体调用, 重复3次, 重复间隔2秒\\\"\\n\" +\n            \"    echo \\\"tt -i 1002 -p --replay-times 3  --replay-interval 2000\\\"\\n\" +\n            \"    echo \\\"# 日志器\\\"\\n\" +\n            \"    echo \\\"logger\\\"\\n\" +\n            \"    echo \\\"# 类加载器列表\\\"\\n\" +\n            \"    echo \\\"classloader -t\\\"\\n\" +\n            \"    echo \\\"history\\\"\\n\" +\n            \"    echo \\\"help\\\"\\n\" +\n            \"    echo \\\"keymap\\\"\\n\" +\n            \"    echo \\\"dashboard\\\"\\n\" +\n            \"    echo \\\"# 清屏\\\"\\n\" +\n            \"    echo \\\"cls\\\"\\n\" +\n            \"    echo \\\"# 线程\\\"\\n\" +\n            \"    echo \\\"thread\\\"\\n\" +\n            \"    echo \\\"thread --state WAITING\\\"\\n\" +\n            \"    echo \\\"thread --state TIMED_WAITING\\\"\\n\" +\n            \"    echo \\\"thread --state RUNNABLE\\\"\\n\" +\n            \"    echo \\\"\\\\n# 退出、关闭等命令, 禁止ctrl + C\\\"\\n\" +\n            \"    echo \\\"# 退出某个命令\\\"\\n\" +\n            \"    echo \\\"Q\\\"\\n\" +\n            \"    echo \\\"# 退出当前arthas-client\\\"\\n\" +\n            \"    echo \\\"quit\\\"\\n\" +\n            \"    echo \\\"# 关闭arthas-server\\\"\\n\" +\n            \"    echo \\\"shutdown\\\"\\n\" +\n            \"}\\n\" +\n            \"\\n\" +\n            \"alias searchPID='searchPID'\\n\" +\n            \"alias killPID='killPID'\\n\" +\n            \"alias searchPortOccupy='searchPortOccupy'\\n\" +\n            \"alias https-downLoadResponse='downLoadResponse'\\n\" +\n            \"alias https-show='show'\\n\" +\n            \"alias https-downLoadExcel='downLoadExcel'\\n\" +\n            \"alias https-downloadD8ger='downloadD8ger'\\n\" +\n            \"\\n\" +\n            \"alias 'xDev=xDev'\\n\" +\n            \"alias 'xDevNormal=xDevNormal'\\n\" +\n            \"alias 'backgroundENV=backgroundENV'\\n\" +\n            \"\\n\" +\n            \"alias 'showssh=ps -ef | grep ssh'\\n\" +\n            \"alias 'tsm=justDoIT'\\n\" +\n            \"# 开隧道\\n\" +\n            \"alias 'iphone4j=nohup sshpass -f TUNNEL_DIR ssh xx@xx.xx.xx.xx -L 11186:xx.xx.xx.xx:1186 -N &'\\n\" +\n            \"\\n\" +\n            \"alias 'ip=ifconfig | grep xxx'\\n\" +\n            \"\\n\" +\n            \"alias 'cph=cph'\\n\" +\n            \"alias 'fkgrep=fkgrep'\\n\" +\n            \"alias 'arthasHelp=arthasHelp'\\n\" +\n            \"# 快速编辑.zshrc\\n\" +\n            \"alias 'vrc=vim ~/.zshrc'\\n\" +\n            \"# 快速展示.zshrc\\n\" +\n            \"alias 'crc=cat ~/.zshrc'\\n\" +\n            \"\\n\" +\n            \"# source ~/.bash_profile\\n\" +\n            \"if [ -f ~/.bash_profile ]; then\\n\" +\n            \"    . ~/.bash_profile;\\n\" +\n            \"fi\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"source $ZSH/oh-my-zsh.sh\\n\";\n\n    public static String TEMPLATE_NASA = \"=========================================NASA=========================================\\n\" +\n            \"Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\\n\" +\n            \"      which these context included will be ignored;\\n\" +\n            \"      2.Multi-lines to be handled must include ','\\n\" +\n            \"      as the split keyword\\n\" +\n            \"      3.config example:\\n\" +\n            \"      - @<prefix=D8(>@         , add 'D8(' before the start of each line\\n\" +\n            \"      - @<suffix=)>@           , add ')' after the end of each line\\n\" +\n            \"      - @<alignStyle=LEFT>@    , you can config CENTER, RIGHT too\\n\" +\n            \"      - @<formatSQL=false>@    , if config SQL then it will append 'AS' alias name\\n\" +\n            \"      - @<formatAsCamel=false>@ , special for SQL column alias camel name\\n\" +\n            \"      4.As example below, one handled what you will find like this:\\n\" +\n            \"      first_name,       --> D8(first_name)        AS  firstName,\\n\" +\n            \"      current_age,      --> D8(current_age)       AS  currentAge,\\n\" +\n            \"      blog_url,         --> D8(blog_url)          AS  blogUrl,\\n\" +\n            \"      graduated_school, --> D8(graduated_school)  AS  graduatedSchool,\\n\" +\n            \"      total_assets      --> D8(total_assets)      AS  totalAssets\\n\" +\n            \"=========================================NASA=========================================\\n\" +\n            \"The next line is very import below, do not modify anything or you'll get nothing\\n\" +\n            \"@D8ger-ALIGN@\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"first_name,\\n\" +\n            \"current_age,\\n\" +\n            \"blog_url,\\n\" +\n            \"graduated_school,\\n\" +\n            \"total_assets\\n\";\n\n    public static String TEMPLATE_END = \"=========================================END=========================================\\n\" +\n            \"Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\\n\" +\n            \"      which these context included will be ignored;\\n\" +\n            \"      2.Considering compatibility separator, Multi-lines to be handled\\n\" +\n            \"      must include ',' or line break or '，' as the split keyword.\\n\" +\n            \"      3.config example:\\n\" +\n            \"      - @<alignStyle=LEFT>@    , LEFT(default) and you can config CENTER, RIGHT too\\n\" +\n            \"      - @<algorithmType=1>@    , 1(default) as 'AES' and 2 as 'PinYin'\\n\" +\n            \"      - @<operateType=0>@      , 1 as encrypt, 2 as decrypt\\n\" +\n            \"                                 and 0(default) is encrypt + decrypt for complete\\n\" +\n            \"      4.As example below, one handled what you will find like this:\\n\" +\n            \"      When algorithmType=1 && operateType = 0\\n\" +\n            \"        MyName -->(first AES encryption) d8gerX==\\n\" +\n            \"               -->(then AES decryption)  MyName\\n\" +\n            \"      When algorithmType=2 && operateType = 0\\n\" +\n            \"        帝八哥  -->(first Fetch Chinese PinYin) dibage\\n\" +\n            \"               -->(then PinYin encryption)     d8gerY==\\n\" +\n            \"               -->(last PinYin decryption)     dibage\\n\" +\n            \"      Other case, just refer the two above.\\n\" +\n            \"=========================================END=========================================\\n\" +\n            \"The next line is very import below, do not modify anything or you'll get nothing\\n\" +\n            \"@D8ger-END@\\n\" +\n            \"\\n\" +\n            \"\\n\" +\n            \"AName\";\n\n    /**\n     * Template rendering\n     *\n     * @param template\n     * @param bindingMap\n     * @return\n     */\n    public static StringBuilder render(@NonNull StringBuilder template, Map<String, StringBuilder> bindingMap) {\n        StringBuilder result = template;\n        for (Map.Entry<String, StringBuilder> entry : bindingMap.entrySet()) {\n            VerbalExpression regex = VerbalExpressionUtil.buildRegex(entry.getKey());\n            result = VerbalExpressionUtil.executePatternRex(regex, result, entry.getValue());\n        }\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/D8gerAutoCoding.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\nimport com.intellij.openapi.module.Module;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport com.intellij.psi.PsiClass;\nimport com.intellij.psi.PsiDirectory;\nimport com.intellij.psi.PsiField;\nimport com.intellij.psi.PsiJavaFile;\nimport com.xyz.caofancpu.d8ger.util.CollectionUtil;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport com.xyz.caofancpu.d8ger.util.IdeaPlatformFileTreeUtil;\nimport com.xyz.caofancpu.d8ger.util.PropertiesUtil;\nimport com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.NonNull;\nimport lombok.experimental.Accessors;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\n\n/**\n * Automatically generate code core classes\n *\n * @author caofanCPU\n */\n@Data\n@NoArgsConstructor\n@Accessors(chain = true)\npublic class D8gerAutoCoding {\n    /**\n     * Project where the current file is located\n     */\n    private Project currentProject;\n\n    /**\n     * Module where the current file is located\n     */\n    private Module currentModule;\n\n    /**\n     * Resource root directory file\n     */\n    private VirtualFile rootResource;\n\n    /**\n     * Automatic code generation directory\n     */\n    private PsiDirectory d8AutoCodeDir;\n\n    /**\n     * Flag of using D8AutoCode directory or not\n     */\n    private boolean useDefaultDirectory;\n\n    /**\n     * Original model file object\n     */\n    private PsiJavaFile originMoJavaFile;\n\n    /**\n     * Original model class object, take only the first one by default\n     */\n    private PsiClass originMoPsiClass;\n\n    /**\n     * Original model class name\n     */\n    private String originMoName;\n\n    /**\n     * Field list of the original model class object\n     */\n    private List<MoField> moFieldList;\n\n    /**\n     * FileMap, value: Pair<Generate file name, Template string>\n     */\n    private Map<KeyEnum, Pair<String, StringBuilder>> fileMap = new HashMap<>(32, 0.75f);\n\n    /**\n     * Template keyword match replacement Map\n     */\n    private Map<String, StringBuilder> keyWordMatchMap = new HashMap<>(32, 0.75f);\n\n    /**\n     * Storage custom config directories that auto code files put into\n     */\n    private Map<KeyEnum, Pair<PsiDirectory, String>> customConfigAutoCodeDirMap = new HashMap<>(16, 0.75f);\n\n    /**\n     * Real need create file, just for marking\n     */\n    private List<KeyEnum> realNeedCreateFileKeyList = new ArrayList<>();\n\n    /**\n     * Construction methods exposed to the outside world,\n     * pay attention to the method execution order\n     *\n     * @param currentProject\n     * @param currentModule\n     * @param rootResource\n     * @param moJavaFile\n     * @return\n     */\n    public static D8gerAutoCoding build(@NonNull Project currentProject, @NonNull Module currentModule, @NonNull VirtualFile rootResource, @NonNull PsiJavaFile moJavaFile) {\n        return new D8gerAutoCoding()\n                // Set the project\n                .setCurrentProject(currentProject)\n                // Set the module\n                .setCurrentModule(currentModule)\n                // config resource root directory file\n                .setRootResource(rootResource)\n                // config directory which current Java file is located\n                .setD8AutoCodeDir(moJavaFile.getContainingDirectory())\n                // Set model type of PsiJavaFile\n                .setOriginMoJavaFile(moJavaFile)\n                // Set model class type of PsiClass\n                .configOriginPsiClass()\n                // Set field list\n                .initMoFieldList()\n                // Config custom directory Map\n                .initCustomConfigAutoCodeDirMap()\n                // Config keyword Map\n                .initKeyWordMap()\n                // Config file Map\n                .initFileMap();\n    }\n\n    /**\n     * File name Map\n     *\n     * @return\n     */\n    private D8gerAutoCoding initFileMap() {\n        fileMap.put(KeyEnum.MO, Pair.of(this.getMoName().concat(ConstantUtil.MO_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO : AutoCodeTemplate.ZN_TEMPLATE_MO));\n        fileMap.put(KeyEnum.SWAGGER_MO, Pair.of(this.getMoName().concat(ConstantUtil.SWAGGER_MO_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_SWAGGER_VO : AutoCodeTemplate.ZN_TEMPLATE_SWAGGER_VO));\n        fileMap.put(KeyEnum.MO_EXAMPLE, Pair.of(this.getMoName().concat(ConstantUtil.MO_EXAMPLE_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO_EXAMPLE : AutoCodeTemplate.ZN_TEMPLATE_MO_EXAMPLE));\n        fileMap.put(KeyEnum.MO_MAPPER, Pair.of(this.getMoName().concat(ConstantUtil.MO_MAPPER_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MAPPER : AutoCodeTemplate.ZN_TEMPLATE_MAPPER));\n        fileMap.put(KeyEnum.MO_HANDLER, Pair.of(this.getMoName().concat(ConstantUtil.MO_HANDLER_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_HANDLER : AutoCodeTemplate.ZN_TEMPLATE_HANDLER));\n        fileMap.put(KeyEnum.MO_CONTROLLER, Pair.of(this.getMoName().concat(ConstantUtil.MO_CONTROLLER_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_CONTROLLER : AutoCodeTemplate.ZN_TEMPLATE_CONTROLLER));\n        fileMap.put(KeyEnum.MO_MAPPER_XML, Pair.of(this.getMoName().concat(ConstantUtil.MO_MAPPER_NAME_SUFFIX).concat(ConstantUtil.XML_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MAPPER_XML : AutoCodeTemplate.ZN_TEMPLATE_MAPPER_XML));\n        fileMap.put(KeyEnum.MO_SQL, Pair.of(this.getMoName().concat(ConstantUtil.SQL_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO_SQL : AutoCodeTemplate.ZN_TEMPLATE_MO_SQL));\n        return this;\n    }\n\n    private List<KeyEnum> getAllFileKeyList() {\n        List<KeyEnum> keyEnumList = new ArrayList<>();\n        keyEnumList.add(KeyEnum.MO);\n        keyEnumList.add(KeyEnum.SWAGGER_MO);\n        keyEnumList.add(KeyEnum.MO_EXAMPLE);\n        keyEnumList.add(KeyEnum.MO_MAPPER);\n        keyEnumList.add(KeyEnum.MO_HANDLER);\n        keyEnumList.add(KeyEnum.MO_CONTROLLER);\n        keyEnumList.add(KeyEnum.MO_MAPPER_XML);\n        keyEnumList.add(KeyEnum.MO_SQL);\n        return keyEnumList;\n    }\n\n    /**\n     * Init custom config directories that auto code files put into\n     *\n     * @return\n     */\n    private D8gerAutoCoding initCustomConfigAutoCodeDirMap() {\n        Properties properties = loadPropertiesFromRootResource();\n        List<KeyEnum> keyEnumList = getAllFileKeyList();\n        keyEnumList.forEach(keyEnum -> {\n            if (PropertiesUtil.checkConfigTakeEffect(properties, keyEnum.getKey())) {\n                realNeedCreateFileKeyList.add(keyEnum);\n            }\n            String directoryPath = PropertiesUtil.detectConfigDirectoryPath(properties, keyEnum.getKey());\n            if (StringUtils.isNotBlank(directoryPath)) {\n                PsiDirectory targetDir = IdeaPlatformFileTreeUtil.getOrCreateSubDirByPath(currentProject, directoryPath);\n                if (Objects.nonNull(targetDir)) {\n                    String targetPackage = VerbalExpressionUtil.convertPathToPackage(directoryPath);\n                    customConfigAutoCodeDirMap.put(keyEnum, Pair.of(targetDir, targetPackage));\n                }\n            }\n        });\n        return this;\n    }\n\n    /**\n     * Load custom config properties\n     *\n     * @return\n     */\n    public Properties loadPropertiesFromRootResource() {\n        return PropertiesUtil.loadPropertiesFromRootResource(this.currentProject);\n    }\n\n    /**\n     * Template keywords Map\n     *\n     * @return\n     */\n    private D8gerAutoCoding initKeyWordMap() {\n        keyWordMatchMap.put(TemplateKeyWordEnum.MO_NAME_KEY.getName(), new StringBuilder(this.getMoName()));\n        keyWordMatchMap.put(TemplateKeyWordEnum.PACKAGE_NAME_KEY.getName(), new StringBuilder(this.getPackageName()));\n        keyWordMatchMap.put(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY.getName(), new StringBuilder(StringUtils.uncapitalize(this.getMoName())));\n        Properties properties = loadPropertiesFromRootResource();\n        keyWordMatchMap.put(TemplateKeyWordEnum.AUTHOR_KEY.getName(), StringUtils.isNotBlank(properties.getProperty(ConstantUtil.CONFIG_AUTHOR_KEY)) ? new StringBuilder(properties.getProperty(ConstantUtil.CONFIG_AUTHOR_KEY)) : new StringBuilder(ConstantUtil.DEFAULT_AUTHOR));\n        String apiUrlPrefix;\n        if (StringUtils.isBlank(properties.getProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY))) {\n            apiUrlPrefix = ConstantUtil.DEFAULT_API_URL_PREFIX;\n        } else {\n            apiUrlPrefix = VerbalExpressionUtil.correctUrl(properties.getProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY));\n        }\n\n        // handle mapper's annotation\n        boolean isMapper = PropertiesUtil.checkConfigTakeEffect(properties, KeyEnum.MO_MAPPER_ANNOTATION.getKey());\n        Pair<String, String> mapperPair = isMapper ? ConstantUtil.BOOT_MAPPER : ConstantUtil.MVC_MAPPER;\n        keyWordMatchMap.put(TemplateKeyWordEnum.MAPPER_ANNOTATION_PACKAGE_KEY.getName(), new StringBuilder(mapperPair.getLeft()));\n        keyWordMatchMap.put(TemplateKeyWordEnum.MAPPER_ANNOTATION_KEY.getName(), new StringBuilder(mapperPair.getRight()));\n\n        keyWordMatchMap.put(TemplateKeyWordEnum.API_URL_PREFIX_KEY.getName(), new StringBuilder(apiUrlPrefix));\n        keyWordMatchMap.put(TemplateKeyWordEnum.MO_FIELD_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toString), ConstantUtil.DOUBLE_NEXT_LINE)));\n        keyWordMatchMap.put(TemplateKeyWordEnum.SWAGGER_MO_FIELD_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toSwaggerString), ConstantUtil.DOUBLE_NEXT_LINE)).append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE).append(wrapSwaggerPage()));\n        keyWordMatchMap.put(TemplateKeyWordEnum.MO_EXAMPLE_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toMoExampleDefinitionMethodString), ConstantUtil.EMPTY)));\n        keyWordMatchMap.put(TemplateKeyWordEnum.SQL_MO_TABLE_KEY.getName(), new StringBuilder(VerbalExpressionUtil.sqlUnderLineName(this.getMoName())));\n        keyWordMatchMap.put(TemplateKeyWordEnum.SQL_MO_COLUMN_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toSqlColumnDefinitionString), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE)));\n\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_BASE_COLUMN_LIST_KEY.getName(), this.getXMLBaseColumnList());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_SELECT_BASE_COLUMN_LIST_KEY.getName(), this.getXMLSelectBaseColumnList());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY.getName(), this.getXMLBatchUpdateNonNullFieldByID());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_COLUMN_LIST_KEY.getName(), this.getXMLInsertSelectiveColumnList());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_FIELD_LIST_KEY.getName(), this.getXMLInsertSelectiveFieldList());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY.getName(), this.getXMLUpdateNonNullFieldByExample());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_COLUMN_LIST_KEY.getName(), this.getXMLInsertField());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_BATCH_INSERT_COLUMN_LIST_KEY.getName(), this.getXMLBatchInsertField());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_ID_KEY.getName(), this.getXMLUpdateNonNullFieldByID());\n        keyWordMatchMap.put(TemplateKeyWordEnum.XML_MO_LIST_QUERY_KEY.getName(), this.getXMLMoListQuery());\n        return this;\n    }\n\n    /**\n     * Enhance swagger model with paging request field\n     *\n     * @return\n     */\n    public String wrapSwaggerPage() {\n        return ConstantUtil.TAB + \"@ApiModelProperty(value = \\\"\" + \"pageNum\" + \"\\\", required = false, example = \\\"1\\\", position = \" + (moFieldList.size() + 1) + \")\" + ConstantUtil.NEXT_LINE\n                + ConstantUtil.TAB + ConstantUtil.DEFAULT_ACCESS_MODIFIER + ConstantUtil.SPACE + SupportFieldTypeEnum.INTEGER.getShortName() + ConstantUtil.SPACE + ConstantUtil.PAGE_NUM_NAME + ConstantUtil.ENGLISH_SEMICOLON + ConstantUtil.NEXT_LINE + ConstantUtil.NEXT_LINE\n                + ConstantUtil.TAB + \"@ApiModelProperty(value = \\\"\" + \"pageSize\" + \"\\\", required = false, example = \\\"10\\\", position = \" + (moFieldList.size() + 2) + \")\" + ConstantUtil.NEXT_LINE\n                + ConstantUtil.TAB + ConstantUtil.DEFAULT_ACCESS_MODIFIER + ConstantUtil.SPACE + SupportFieldTypeEnum.INTEGER.getShortName() + ConstantUtil.SPACE + ConstantUtil.PAGE_SIZE_NAME + ConstantUtil.ENGLISH_SEMICOLON;\n    }\n\n    /**\n     * To improve performance, only the internal key is selected for each file to reduce the number of string replacements\n     *\n     * @param key\n     * @return\n     */\n    public Map<String, StringBuilder> loadEnhanceKeyWordMap(KeyEnum key) {\n        Map<String, StringBuilder> resultMap = new HashMap<>(32, 0.65f);\n        if (KeyEnum.FORMAT_STYLE == key) {\n            return resultMap;\n        }\n        List<TemplateKeyWordEnum> keyWordEnumList = new ArrayList<>(TemplateKeyWordEnum.values().length);\n        switch (key) {\n            case MO:\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_FIELD_KEY);\n                break;\n            case SWAGGER_MO:\n                keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_FIELD_KEY);\n                break;\n            case MO_EXAMPLE:\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_KEY);\n                break;\n            case MO_MAPPER_XML:\n                keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_SELECT_BASE_COLUMN_LIST_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_TABLE_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_ID_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_BASE_COLUMN_LIST_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_BATCH_INSERT_COLUMN_LIST_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_MO_LIST_QUERY_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_COLUMN_LIST_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_COLUMN_LIST_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_FIELD_LIST_KEY);\n                break;\n            case MO_SQL:\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_TABLE_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_COLUMN_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                break;\n            case MO_MAPPER:\n                keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_ANNOTATION_PACKAGE_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_ANNOTATION_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY);\n                break;\n            case MO_HANDLER:\n                keyWordEnumList.add(TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY);\n                break;\n            case MO_CONTROLLER:\n                keyWordEnumList.add(TemplateKeyWordEnum.CONTROLLER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY);\n                keyWordEnumList.add(TemplateKeyWordEnum.API_URL_PREFIX_KEY);\n                break;\n        }\n        Map<String, StringBuilder> keyWordMatchMap = getKeyWordMatchMap();\n        keyWordEnumList.forEach(templateKey -> resultMap.put(templateKey.getName(), keyWordMatchMap.get(templateKey.getName())));\n        return resultMap;\n    }\n\n    /**\n     * Encapsulating model field object\n     *\n     * @return\n     */\n    private D8gerAutoCoding initMoFieldList() {\n        PsiField[] selfOwnedFields = this.originMoPsiClass.getFields();\n        // extract original field list\n        this.setMoFieldList(CollectionUtil.transToList(Arrays.asList(selfOwnedFields), MoField::new));\n        // enhance by configuration\n        Properties properties = loadPropertiesFromRootResource();\n        // Language configuration\n        if (ConstantUtil.OPTIONAL_CONFIG_LANGUAGE.equals(properties.getProperty(ConstantUtil.CONFIG_LANGUAGE_KEY))) {\n            // Annotation Chinese Culture\n            AutoCodeTemplate.IS_EN_LOCALE = Boolean.FALSE;\n        } else {\n            AutoCodeTemplate.IS_EN_LOCALE = Boolean.TRUE;\n        }\n        if (Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID)))) {\n            this.produceIdField();\n        }\n        // whether auto generate create_time and update_time column definition by custom config\n        boolean sqlDetectTimeColumn = PropertiesUtil.checkConfigTakeEffect(properties, KeyEnum.SQL_DETECT_TIME_COLUMN.getKey());\n        if (sqlDetectTimeColumn && Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_CREATE_TIME)))) {\n            this.produceCreateTimeField();\n        }\n        if (sqlDetectTimeColumn && Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_UPDATE_TIME)))) {\n            this.produceUpdateTimeField();\n        }\n        // Set field order\n        moFieldList.forEach(item -> item.setIndex(moFieldList.indexOf(item)));\n        return this;\n    }\n\n    /**\n     * Get enum field type\n     *\n     * @return\n     */\n    public List<String> getEnumTypeClassName() {\n        return CollectionUtil.filterAndTransList(moFieldList, item -> SupportFieldTypeEnum.ENUM.getOriginName().equals(item.getFieldOriginTypeName()), MoField::getFieldTypeShortName);\n    }\n\n    /**\n     * Model name\n     *\n     * @return\n     */\n    public String getMoName() {\n        String originMoName = Objects.nonNull(this.getOriginMoName()) ? this.getOriginMoName() : VerbalExpressionUtil.cropMoSuffix(originMoJavaFile.getClasses()[0].getName());\n        this.setOriginMoName(originMoName);\n        return originMoName;\n    }\n\n    /**\n     * package name\n     *\n     * @return\n     */\n    public String getPackageName() {\n        return originMoJavaFile.getPackageName() + ConstantUtil.ENGLISH_FULL_STOP + ConstantUtil.GENERATE_DIR;\n    }\n\n    /**\n     * SQL-BaseColumnList, exclude primary key column `id` | `createTime` | `updateTime`\n     * example:\n     * `name`,\n     * `hello_d8ger`\n     *\n     * @return\n     */\n    private StringBuilder getXMLBaseColumnList() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME),\n                item -> ConstantUtil.TRIPLE_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`\"\n        ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-SelectBaseColumnList(with alias name)\n     * example:\n     * `id` AS id,\n     * `name` AS name,\n     * `hello_d8ger` AS helloD8ger\n     *\n     * @return\n     */\n    private StringBuilder getXMLSelectBaseColumnList() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList,\n                item -> ConstantUtil.TRIPLE_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"` AS \" + item.getName()\n        ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-BatchUpdateNonNullFieldByID\n     *\n     * @return\n     */\n    private StringBuilder getXMLBatchUpdateNonNullFieldByID() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID),\n                item -> ConstantUtil.QUATERNARY_TAB + \"<if test=\\\"item.\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.PENTA_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`\" + ConstantUtil.SPACE + \"=\" + ConstantUtil.SPACE + \"#{item.\" + item.getName() + \"},\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.QUATERNARY_TAB + \"</if>\"\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-NonNullColumnList\n     *\n     * @return\n     */\n    private StringBuilder getXMLInsertSelectiveColumnList() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID),\n                item -> ConstantUtil.TRIPLE_TAB + \"<if test=\\\"\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.QUATERNARY_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`,\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.TRIPLE_TAB + \"</if>\"\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-NonNullInsertField\n     *\n     * @return\n     */\n    private StringBuilder getXMLInsertSelectiveFieldList() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID),\n                item -> ConstantUtil.TRIPLE_TAB + \"<if test=\\\"\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.QUATERNARY_TAB + \"#{\" + item.getName() + \"},\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.TRIPLE_TAB + \"</if>\"\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-UpdateNonNullFieldByExample, exclude primary key column `id`\n     *\n     * @return\n     */\n    private StringBuilder getXMLUpdateNonNullFieldByExample() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID),\n                item -> ConstantUtil.TRIPLE_TAB + \"<if test=\\\"record.\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.QUATERNARY_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`\" + ConstantUtil.SPACE + \"=\" + ConstantUtil.SPACE + \"#{record.\" + item.getName() + \"},\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.TRIPLE_TAB + \"</if>\"\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-Insert, exclude primary key column `id` | `createTime` | `updateTime`\n     *\n     * @return\n     */\n    private StringBuilder getXMLInsertField() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME),\n                item -> ConstantUtil.TRIPLE_TAB + \"#{\" + item.getName() + \"}\"\n        ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-BatchInsertField, exclude primary key column `id` | `createTime` | `updateTime`\n     *\n     * @return\n     */\n    private StringBuilder getXMLBatchInsertField() {\n        return new StringBuilder(ConstantUtil.TRIPLE_TAB).append(\"(\").append(ConstantUtil.NEXT_LINE)\n                .append(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                        item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME),\n                        item -> ConstantUtil.QUATERNARY_TAB + \"#{item.\" + item.getName() + \"}\"\n                ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE))\n                .append(ConstantUtil.NEXT_LINE).append(ConstantUtil.TRIPLE_TAB).append(\")\");\n    }\n\n    /**\n     * SQL-UpdateNonNullFieldByID\n     *\n     * @return\n     */\n    private StringBuilder getXMLUpdateNonNullFieldByID() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList,\n                item -> item.getName().equals(ConstantUtil.SQL_ID),\n                item -> ConstantUtil.TRIPLE_TAB + \"<if test=\\\"\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.QUATERNARY_TAB + \"`\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`\" + ConstantUtil.SPACE + \"=\" + ConstantUtil.SPACE + \"#{\" + item.getName() + \"},\" + ConstantUtil.NEXT_LINE\n                        + ConstantUtil.TRIPLE_TAB + \"</if>\"\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * SQL-QueryModelList\n     *\n     * @return\n     */\n    private StringBuilder getXMLMoListQuery() {\n        return new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList,\n                item -> {\n                    String tmp;\n                    if (SupportFieldTypeEnum.STRING.getShortName().equals(item.getFieldTypeShortName())) {\n                        tmp = \"LIKE \" + \"CONCAT(#{\" + item.getName() + \"}, '%')\";\n                    } else {\n                        tmp = \"=\" + ConstantUtil.SPACE + \"#{\" + item.getName() + \"}\";\n                    }\n                    return ConstantUtil.TRIPLE_TAB + \"<if test=\\\"\" + item.getName() + ConstantUtil.SPACE + \"!= null\\\">\" + ConstantUtil.NEXT_LINE\n                            + ConstantUtil.QUATERNARY_TAB + \"AND `\" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + \"`\" + ConstantUtil.SPACE + tmp + ConstantUtil.NEXT_LINE\n                            + ConstantUtil.TRIPLE_TAB + \"</if>\";\n                }\n        ), ConstantUtil.NEXT_LINE));\n    }\n\n    /**\n     * Config origin Model class\n     *\n     * @return\n     */\n    public D8gerAutoCoding configOriginPsiClass() {\n        return this.setOriginMoPsiClass(originMoJavaFile.getClasses()[0]);\n    }\n\n    /**\n     * For an optional, auto add 'id' field\n     */\n    private void produceIdField() {\n        String comment = StringUtils.upperCase(ConstantUtil.SQL_ID);\n        SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LONG;\n        MoField idField = new MoField()\n                .setComment(comment)\n                .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER)\n                .setFieldOriginTypeName(idFieldType.getOriginName())\n                .setFieldTypeShortName(idFieldType.getShortName())\n                .setFieldSqlTypeName(idFieldType.getSqlName())\n                .setName(ConstantUtil.SQL_ID);\n        this.moFieldList.add(0, idField);\n    }\n\n    /**\n     * For an optional, auto add 'createTime' field\n     */\n    private void produceCreateTimeField() {\n        String comment = AutoCodeTemplate.IS_EN_LOCALE ? ConstantUtil.SQL_CREATE_TIME : ConstantUtil.ZN_SQL_CREATE_TIME;\n        SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LOCAL_DATE_TIME;\n        MoField idField = new MoField()\n                .setComment(comment)\n                .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER)\n                .setFieldOriginTypeName(idFieldType.getOriginName())\n                .setFieldTypeShortName(idFieldType.getShortName())\n                .setFieldSqlTypeName(idFieldType.getSqlName())\n                .setName(ConstantUtil.SQL_CREATE_TIME);\n        this.moFieldList.add(idField);\n    }\n\n    /**\n     * For an optional, auto add 'updateTime' field\n     */\n    private void produceUpdateTimeField() {\n        String comment = AutoCodeTemplate.IS_EN_LOCALE ? ConstantUtil.SQL_UPDATE_TIME : ConstantUtil.ZN_SQL_UPDATE_TIME;\n        SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LOCAL_DATE_TIME;\n        MoField idField = new MoField()\n                .setComment(comment)\n                .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER)\n                .setFieldOriginTypeName(idFieldType.getOriginName())\n                .setFieldTypeShortName(idFieldType.getShortName())\n                .setFieldSqlTypeName(idFieldType.getSqlName())\n                .setName(ConstantUtil.SQL_UPDATE_TIME);\n        this.moFieldList.add(idField);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/EasterEggCodeTemplateEnum.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\n/**\n * EasterEgg code template keyword enumeration\n *\n * @author caofanCPU\n */\npublic enum EasterEggCodeTemplateEnum {\n    D8GER_CONFIG_FILE_KEY(\"D8GER\", AutoCodeTemplate.TEMPLATE_D8GER),\n    REGEX_CONFIG_FILE_KEY(\"REGEX\", AutoCodeTemplate.TEMPLATE_REGEX),\n    OH_MY_ZSH_CONFIG_FILE_KEY(\"OHMYZSH\", AutoCodeTemplate.TEMPLATE_OH_MY_ZSH),\n    END_CONFIG_FILE_KEY(\"END\", AutoCodeTemplate.TEMPLATE_END),\n\n\n    NASA_CONFIG_FILE_KEY(\"NASA\", AutoCodeTemplate.TEMPLATE_NASA),\n    ;\n\n\n    private String codeKey;\n\n    private String templateCode;\n\n    EasterEggCodeTemplateEnum(String codeKey, String templateCode) {\n        this.codeKey = codeKey;\n        this.templateCode = templateCode;\n    }\n\n    public String getCodeKey() {\n        return codeKey;\n    }\n\n    public String getTemplateCode() {\n        return templateCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/KeyEnum.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\n/**\n * Generate file enum\n *\n * @author caofanCPU\n */\npublic enum KeyEnum {\n    MO(\"autoCreateMo\"),\n    SWAGGER_MO(\"autoCreateSwaggerMo\"),\n    MO_MAPPER(\"autoCreateMapper\"),\n    MO_EXAMPLE(\"autoCreateExample\"),\n    MO_MAPPER_XML(\"autoCreateXML\"),\n    MO_HANDLER(\"autoCreateHandler\"),\n    MO_CONTROLLER(\"autoCreateController\"),\n    MO_SQL(\"autoCreateDefinitionSQL\"),\n    FORMAT_STYLE(\"autoFormatStyle\"),\n    SQL_DETECT_TIME_COLUMN(\"autoDetectSQLTimeColumn\"),\n    MO_MAPPER_ANNOTATION(\"mapperBetterThenRepository\"),\n    ;\n\n    private String key;\n\n    KeyEnum(String key) {\n        this.key = key;\n    }\n\n    /**\n     * Judge create file or not\n     *\n     * @param key\n     * @return\n     */\n    @Deprecated\n    public static boolean ignoreCreateFile(KeyEnum key) {\n        return MO_CONTROLLER == key;\n    }\n\n    /**\n     * Judge import enumeration classes or not in Java files\n     *\n     * @param key\n     * @return\n     */\n    public static boolean needImportEnumClass(KeyEnum key) {\n        return MO == key || SWAGGER_MO == key || MO_EXAMPLE == key;\n    }\n\n    public String getKey() {\n        return key;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/MoField.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\nimport com.intellij.psi.PsiElement;\nimport com.intellij.psi.PsiField;\nimport com.intellij.psi.PsiIdentifier;\nimport com.intellij.psi.PsiModifierList;\nimport com.intellij.psi.PsiTypeElement;\nimport com.intellij.psi.impl.source.tree.PsiCommentImpl;\nimport com.intellij.psi.javadoc.PsiDocComment;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.NonNull;\nimport lombok.experimental.Accessors;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.Objects;\n\n/**\n * Model encapsulated object\n *\n * @author caofanCPU\n */\n@Data\n@NoArgsConstructor\n@Accessors(chain = true)\npublic class MoField {\n    /**\n     * Field comment(name)\n     */\n    private String comment;\n\n    /**\n     * Access modifier, private is used by default\n     */\n    private String accessModifier;\n\n    /**\n     * Field primitive type name\n     */\n    private String fieldOriginTypeName;\n\n    /**\n     * Field type abbreviation\n     */\n    private String fieldTypeShortName;\n\n    /**\n     * Field SQL Type Name\n     */\n    private String fieldSqlTypeName;\n\n    /**\n     * Field Name\n     */\n    private String name;\n\n    /**\n     * Field order\n     */\n    private int index;\n\n    public MoField(@NonNull PsiField field) {\n        PsiElement[] children = field.getChildren();\n        for (PsiElement child : children) {\n            if (child instanceof PsiCommentImpl || child instanceof PsiDocComment) {\n                this.comment = VerbalExpressionUtil.extractComment(child.getText()).trim();\n                continue;\n            }\n            if (child instanceof PsiModifierList) {\n                this.accessModifier = child.getText();\n                continue;\n            }\n            if (child instanceof PsiTypeElement) {\n                if (Objects.nonNull(child.getText()) && StringUtils.containsIgnoreCase(child.getText(), ConstantUtil.ENUM_SUFFIX)) {\n                    // Enums or enums with names that are enumerated\n                    this.fieldOriginTypeName = SupportFieldTypeEnum.ENUM.getOriginName();\n                    this.fieldTypeShortName = child.getText();\n                    this.fieldSqlTypeName = SupportFieldTypeEnum.ENUM.getSqlName();\n                } else {\n                    SupportFieldTypeEnum fieldTypeEnum = SupportFieldTypeEnum.positionByShortName(child.getText());\n                    this.fieldOriginTypeName = fieldTypeEnum.getOriginName();\n                    this.fieldTypeShortName = fieldTypeEnum.getShortName();\n                    this.fieldSqlTypeName = fieldTypeEnum.getSqlName();\n                }\n                continue;\n            }\n            if (child instanceof PsiIdentifier) {\n                this.name = child.getText();\n            }\n        }\n        if (Objects.isNull(this.comment)) {\n            this.comment = ConstantUtil.EMPTY;\n        }\n        if (Objects.isNull(this.accessModifier)) {\n            this.accessModifier = ConstantUtil.DEFAULT_ACCESS_MODIFIER;\n        }\n    }\n\n    /**\n     * SQL columns field type display\n     *\n     * @return\n     */\n    public String wrapSqlDefaultValueView() {\n        if (Objects.isNull(fieldSqlTypeName)) {\n            return ConstantUtil.EMPTY;\n        }\n        if (fieldSqlTypeName.contains(\"int\")) {\n            return \"default 0 null\";\n        }\n        if (fieldSqlTypeName.contains(\"double\")) {\n            return \"default 0.00 null\";\n        }\n        if (fieldSqlTypeName.contains(\"datetime\")) {\n            return name.equals(ConstantUtil.SQL_UPDATE_TIME) ? \"default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP\" : \"default CURRENT_TIMESTAMP null\";\n        }\n        return \"default '' null\";\n    }\n\n    @Override\n    public String toString() {\n        return ConstantUtil.TAB + \"/**\\n\"\n                + ConstantUtil.TAB + ConstantUtil.SPACE + \"*\" + ConstantUtil.SPACE + comment + \"\\n\"\n                + ConstantUtil.TAB + ConstantUtil.SPACE + \"*/\" + \"\\n\"\n                + ConstantUtil.TAB + accessModifier + ConstantUtil.SPACE + fieldTypeShortName + ConstantUtil.SPACE + name + ConstantUtil.ENGLISH_SEMICOLON;\n    }\n\n    /**\n     * Swagger fields\n     *\n     * @return\n     */\n    public String toSwaggerString() {\n        return ConstantUtil.TAB + \"@ApiModelProperty(value = \\\"\" + comment + \"\\\", required = false, example = \\\"\\\", position = \" + (index + 1) + \")\" + ConstantUtil.NEXT_LINE\n                + ConstantUtil.TAB + accessModifier + ConstantUtil.SPACE + fieldTypeShortName + ConstantUtil.SPACE + name + ConstantUtil.ENGLISH_SEMICOLON;\n    }\n\n    /**\n     * SQL columns definition field\n     *\n     * @return\n     */\n    public String toSqlColumnDefinitionString() {\n        if (name.equals(ConstantUtil.SQL_ID)) {\n            return ConstantUtil.TAB + ConstantUtil.SQL_ID + ConstantUtil.SPACE + fieldSqlTypeName + ConstantUtil.SPACE + \"unsigned auto_increment\" + ConstantUtil.SPACE + \"comment\" + ConstantUtil.SPACE + \"'\" + comment + \"'\" + ConstantUtil.SPACE + \"primary key\";\n        }\n\n        return ConstantUtil.TAB + VerbalExpressionUtil.sqlUnderLineName(name) + ConstantUtil.SPACE + fieldSqlTypeName + ConstantUtil.SPACE + wrapSqlDefaultValueView() + ConstantUtil.SPACE + \"comment\" + ConstantUtil.SPACE + \"'\" + comment + \"'\";\n    }\n\n    /**\n     * SQL operating methods by using example object\n     *\n     * @return\n     */\n    public String toMoExampleDefinitionMethodString() {\n        String capitalizeName = StringUtils.capitalize(name);\n        String sqlColumnName = VerbalExpressionUtil.sqlUnderLineName(name);\n        String javaTypeShortName = fieldTypeShortName;\n        String fieldTypeInListShortName = SupportFieldTypeEnum.BASIC_INT.getShortName().equals(fieldOriginTypeName) ? SupportFieldTypeEnum.INTEGER.getShortName() : StringUtils.capitalize(javaTypeShortName);\n        StringBuilder builder = new StringBuilder();\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Is Null\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"IsNull() {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"is null\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"IS Not Null\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"IsNotNull() {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"is not null\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Equal\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"EqualTo(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"=\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Not Equal\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"NotEqualTo(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"<>\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Greater Than\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"GreaterThan(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\">\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Greater Than Or Equal To\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"GreaterThanOrEqualTo(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\">=\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Less Than\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"LessThan(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"<\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Less Than Or Equal To\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"LessThanOrEqualTo(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"<=\\\", value, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"In\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"In(List<\").append(fieldTypeInListShortName).append(\">\").append(ConstantUtil.SPACE).append(\"values) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"in\\\", values, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Not In\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"NotIn(List<\").append(fieldTypeInListShortName).append(\">\").append(ConstantUtil.SPACE).append(\"values) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"not in\\\", values, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Between\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"Between(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value1,\").append(ConstantUtil.SPACE).append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value2) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"between\\\", value1, value2, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Not Between\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"NotBetween(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value1,\").append(ConstantUtil.SPACE).append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value2) {\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"not between\\\", value1, value2, \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        if (SupportFieldTypeEnum.STRING.getShortName().equals(fieldTypeShortName)) {\n            // 字符串字段, 添加前缀模糊查询\n            builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Like\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"Like(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"like\\\", value + \\\"%\\\", \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n            builder.append(ConstantUtil.DOUBLE_TAB).append(\"/**\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append(\"Not Like\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*\").append(ConstantUtil.SPACE).append(\"@return\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append(\"*/\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(\"public Criteria and\").append(capitalizeName).append(\"NotLike(\").append(javaTypeShortName).append(ConstantUtil.SPACE).append(\"value) {\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.TRIPLE_TAB).append(\"addCriterion(\\\"\").append(sqlColumnName).append(ConstantUtil.SPACE).append(\"not like\\\", value + \\\"%\\\", \\\"\").append(name).append(\"\\\");\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.TRIPLE_TAB).append(\"return (Criteria) this;\").append(ConstantUtil.NEXT_LINE)\n                    .append(ConstantUtil.DOUBLE_TAB).append(\"}\").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE);\n        }\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/ProjectEnvHandler.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.actionSystem.CommonDataKeys;\nimport com.intellij.openapi.actionSystem.PlatformDataKeys;\nimport com.intellij.openapi.module.Module;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.roots.FileIndexFacade;\nimport com.intellij.openapi.roots.ModuleRootManager;\nimport com.intellij.openapi.ui.Messages;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport com.intellij.psi.PsiFile;\nimport com.intellij.psi.PsiJavaFile;\nimport org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;\n\nimport java.util.Objects;\n\n/**\n * Initialize the project environment parameters\n *\n * @author caofanCPU\n */\npublic class ProjectEnvHandler {\n\n    public static D8gerAutoCoding checkAndInitEnv(AnActionEvent e) {\n        PsiFile currentPsiFile = e.getData(CommonDataKeys.PSI_FILE);\n        if (Objects.isNull(currentPsiFile) || !(currentPsiFile instanceof PsiJavaFile)) {\n            Messages.showErrorDialog(\"No .java file chosen\", \"Initialize Environment Error\");\n            return null;\n        }\n\n        PsiJavaFile currentJavaFile = (PsiJavaFile) currentPsiFile;\n        if (currentJavaFile.getClasses().length == 0) {\n            Messages.showErrorDialog(\"No class defined in current chosen .java file\", \"Initialize Environment Error\");\n            return null;\n        }\n\n        Project currentProject = e.getData(PlatformDataKeys.PROJECT);\n        if (Objects.isNull(currentProject)) {\n            Messages.showErrorDialog(\"Not included in a project for current chosen .java file\", \"Initialize Environment Error\");\n            return null;\n        }\n\n        Module currentModule = FileIndexFacade.getInstance(currentProject).getModuleForFile(currentPsiFile.getVirtualFile());\n        if (Objects.isNull(currentModule)) {\n            Messages.showErrorDialog(\"Not included in a module for current chosen .java file\", \"Initialize Environment Error\");\n            return null;\n        }\n        VirtualFile rootResource = ModuleRootManager.getInstance(currentModule).getSourceRoots(JavaModuleSourceRootTypes.RESOURCES).get(0);\n        if (!rootResource.isDirectory()) {\n            Messages.showErrorDialog(\"No resource directory for the project where the current .java file is located\", \"Initialize Environment Error\");\n        }\n        // Initialize the core class\n        return D8gerAutoCoding.build(currentProject, currentModule, rootResource, currentJavaFile);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/SupportFieldTypeEnum.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\nimport com.xyz.caofancpu.d8ger.util.CollectionUtil;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Function;\n\n/**\n * Support field types for Model\n *\n * @author caofanCPU\n */\npublic enum SupportFieldTypeEnum {\n    INTEGER(\"java.lang.Integer\", \"Integer\", \"int(11)\"),\n    BASIC_INT(\"int\", \"int\", \"int(11)\"),\n    LONG(\"java.lang.Long\", \"Long\", \"bigint(20)\"),\n    BASIC_LONG(\"long\", \"long\", \"bigint(20)\"),\n    STRING(\"java.lang.String\", \"String\", \"varchar(32)\"),\n    BOOLEAN(\"java.lang.Boolean\", \"Boolean\", \"tinyint(1)\"),\n    DATE(\"java.util.Date\", \"Date\", \"datetime\"),\n    LOCAL_DATE_TIME(\"java.time.LocalDateTime\", \"LocalDateTime\", \"datetime\"),\n    BIG_DECIMAL(\"java.math.BigDecimal\", \"BigDecimal\", \"double(8, 2)\"),\n    DOUBLE(\"java.lang.Double\", \"Double\", \"double(8, 2)\"),\n    FLOAT(\"java.lang.Float\", \"Float\", \"double(8, 2)\"),\n    SHORT(\"java.lang.Short\", \"Short\", \"int(4)\"),\n    BASIC_DOUBLE(\"double\", \"double\", \"double(8, 2)\"),\n    BASIC_FLOAT(\"float\", \"float\", \"double(8, 2)\"),\n    BASIC_SHORT(\"short\", \"short\", \"int(4)\"),\n    BASIC_BOOLEAN(\"boolean\", \"boolean\", \"tinyint(1)\"),\n    ENUM(\"java.lang.Enum\", null, \"int(4)\"),\n    NONE(null, null, null);\n\n    private String originName;\n\n    private String shortName;\n\n    private String sqlName;\n\n    SupportFieldTypeEnum(String originName, String shortName, String sqlName) {\n        this.originName = originName;\n        this.shortName = shortName;\n        this.sqlName = sqlName;\n    }\n\n    public static SupportFieldTypeEnum positionByShortName(String shortName) {\n        List<SupportFieldTypeEnum> noneNullEnumList = CollectionUtil.removeAndTransList(Arrays.asList(SupportFieldTypeEnum.values()),\n                item -> item == SupportFieldTypeEnum.NONE || item == SupportFieldTypeEnum.ENUM,\n                Function.identity()\n        );\n        SupportFieldTypeEnum result = CollectionUtil.findFirst(noneNullEnumList, item -> item.getShortName().equals(shortName));\n        if (Objects.nonNull(result)) {\n            return result;\n        }\n        return SupportFieldTypeEnum.NONE;\n    }\n\n    public String getOriginName() {\n        return originName;\n    }\n\n    public String getShortName() {\n        return shortName;\n    }\n\n    public SupportFieldTypeEnum setShortName(String shortName) {\n        this.shortName = shortName;\n        return this;\n    }\n\n    public String getSqlName() {\n        return sqlName;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/core/TemplateKeyWordEnum.java",
    "content": "package com.xyz.caofancpu.d8ger.core;\n\n/**\n * Template keyword enum\n *\n * @author caofanCPU\n */\npublic enum TemplateKeyWordEnum {\n    MO_NAME_KEY(\"@MoName@\"),\n    PACKAGE_NAME_KEY(\"@package@\"),\n    UNCAPITALLIZE_MO_NAME_KEY(\"@uncapitallizeMoName@\"),\n    AUTHOR_KEY(\"@d8Author@\"),\n    MO_FIELD_KEY(\"@field@\"),\n    SWAGGER_MO_FIELD_KEY(\"@swaggerField@\"),\n    SQL_MO_TABLE_KEY(\"@mo_table_name@\"),\n    MO_EXAMPLE_KEY(\"@ExampleDefinitionMethod@\"),\n    SQL_MO_COLUMN_KEY(\"@sql_column@\"),\n    XML_BASE_COLUMN_LIST_KEY(\"@BaseColumnList@\"),\n    XML_SELECT_BASE_COLUMN_LIST_KEY(\"@SelectBaseColumnList@\"),\n    XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY(\"@BatchUpdateNonNullFieldByID@\"),\n    XML_UPDATE_NONNULL_FIELD_BY_ID_KEY(\"@UpdateNonNullFieldByID@\"),\n    XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY(\"@UpdateNonNullFieldByExample@\"),\n    XML_INSERT_COLUMN_LIST_KEY(\"@InsertField@\"),\n    XML_BATCH_INSERT_COLUMN_LIST_KEY(\"@BatchInsertField@\"),\n    XML_INSERT_SELECTIVE_COLUMN_LIST_KEY(\"@NonNullColumnList@\"),\n    XML_INSERT_SELECTIVE_FIELD_LIST_KEY(\"@NonNullInsertField@\"),\n    XML_MO_LIST_QUERY_KEY(\"@MoListQuery@\"),\n    API_URL_PREFIX_KEY(\"@apiUrlPrefix@\"),\n\n    MO_PACKAGE_NAME_KEY(\"@moPackage@\"),\n    MAPPER_PACKAGE_NAME_KEY(\"@mapperPackage@\"),\n    MAPPER_ANNOTATION_KEY(\"@MapperAnnotation@\"),\n    MAPPER_ANNOTATION_PACKAGE_KEY(\"@MapperAnnotationPackage@\"),\n    MO_EXAMPLE_PACKAGE_NAME_KEY(\"@moExamplePackage@\"),\n    SWAGGER_MO_PACKAGE_NAME_KEY(\"@swaggerMoPackage@\"),\n    HANDLER_PACKAGE_NAME_KEY(\"@handlerPackage@\"),\n    CONTROLLER_PACKAGE_NAME_KEY(\"@controllerPackage@\"),\n    ;\n\n\n    private String name;\n\n    TemplateKeyWordEnum(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerApplicationState.java",
    "content": "package com.xyz.caofancpu.d8ger.setting;\n\nimport com.intellij.openapi.components.PersistentStateComponent;\nimport com.intellij.openapi.components.ServiceManager;\nimport com.intellij.openapi.components.State;\nimport com.intellij.openapi.components.Storage;\nimport com.intellij.util.xmlb.XmlSerializerUtil;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * D8gerSetting State Service\n *\n * @author D8GER\n */\n@State(\n        name = \"com.xyz.caofancpu.d8ger.setting.D8gerApplicationState\",\n        storages = {@Storage(\"D8gerAutoCodePluginGlobalSetting.xml\")}\n)\npublic class D8gerApplicationState implements PersistentStateComponent<D8gerApplicationState> {\n    public String version = \"1.0\";\n\n    public static D8gerApplicationState getInstance() {\n        return ServiceManager.getService(D8gerApplicationState.class);\n    }\n\n    public static String getOldVersion() {\n        return getInstance().version;\n    }\n\n    public static void setPluginVersion(String version) {\n        getInstance().setVersion(version);\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    @Nullable\n    @Override\n    public D8gerApplicationState getState() {\n        return this;\n    }\n\n    @Override\n    public void loadState(@NotNull D8gerApplicationState d8gerState) {\n        XmlSerializerUtil.copyBean(d8gerState, this);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerProjectState.java",
    "content": "package com.xyz.caofancpu.d8ger.setting;\n\nimport com.intellij.openapi.components.PersistentStateComponent;\nimport com.intellij.openapi.components.ServiceManager;\nimport com.intellij.openapi.components.State;\nimport com.intellij.openapi.components.Storage;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.util.xmlb.XmlSerializerUtil;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * D8gerSetting State Service\n *\n * @author D8GER\n */\n@State(\n        name = \"com.xyz.caofancpu.d8ger.setting.D8gerProjectState\",\n        storages = {@Storage(\"D8gerAutoCodePluginProjectSetting.xml\")}\n)\npublic class D8gerProjectState implements PersistentStateComponent<D8gerProjectState> {\n    public boolean moCheck = true;\n    public boolean mapperCheck = true;\n    public boolean mapperExampleCheck = true;\n    public boolean mapperXmlCheck = true;\n    public boolean sqlCheck = true;\n    public boolean voCheck = false;\n    public boolean handlerCheck = false;\n    public boolean controllerCheck = false;\n    public boolean formatStyleCheck = true;\n    public boolean detectSQLTimeColumnCheck = true;\n    public boolean mapperBetterThenRepositoryCheck = true;\n\n    public String moPath = ConstantUtil.EMPTY;\n    public String mapperPath = ConstantUtil.EMPTY;\n    public String mapperExamplePath = ConstantUtil.EMPTY;\n    public String mapperXmlPath = ConstantUtil.EMPTY;\n    public String sqlPath = ConstantUtil.EMPTY;\n    public String voPath = ConstantUtil.EMPTY;\n    public String handlerPath = ConstantUtil.EMPTY;\n    public String controllerPath = ConstantUtil.EMPTY;\n    public String defaultAuthor = ConstantUtil.DEFAULT_AUTHOR;\n    public String defaultUrlPrefix = ConstantUtil.DEFAULT_API_URL_PREFIX;\n    public String defaultLocale = ConstantUtil.OPTIONAL_CONFIG_LANGUAGE;\n\n    public static D8gerProjectState getInstance(Project currentProject) {\n        return ServiceManager.getService(currentProject, D8gerProjectState.class);\n    }\n\n    @Nullable\n    @Override\n    public D8gerProjectState getState() {\n        return this;\n    }\n\n    @Override\n    public void loadState(@NotNull D8gerProjectState d8GerProjectState) {\n        XmlSerializerUtil.copyBean(d8GerProjectState, this);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSetting.form",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class=\"com.xyz.caofancpu.d8ger.setting.D8gerSetting\">\n  <grid id=\"27dc6\" binding=\"rootPanel\" layout-manager=\"GridLayoutManager\" row-count=\"15\" column-count=\"3\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n    <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n    <constraints>\n      <xy x=\"20\" y=\"20\" width=\"700\" height=\"577\"/>\n    </constraints>\n    <properties>\n      <opaque value=\"true\"/>\n    </properties>\n    <border type=\"none\"/>\n    <children>\n      <component id=\"4c89b\" class=\"javax.swing.JCheckBox\" binding=\"moCheck\">\n        <constraints>\n          <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoCreateMo\"/>\n        </properties>\n      </component>\n      <component id=\"d4069\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"moPath\">\n        <constraints>\n          <grid row=\"1\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <enabled value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"94888\" class=\"javax.swing.JCheckBox\" binding=\"mapperCheck\">\n        <constraints>\n          <grid row=\"2\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoCreateMapper\"/>\n        </properties>\n      </component>\n      <component id=\"2eed7\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"mapperPath\">\n        <constraints>\n          <grid row=\"2\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"3df3d\" class=\"javax.swing.JCheckBox\" binding=\"mapperExampleCheck\">\n        <constraints>\n          <grid row=\"3\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoCreateExample\"/>\n        </properties>\n      </component>\n      <component id=\"8feae\" class=\"javax.swing.JCheckBox\" binding=\"mapperXmlCheck\">\n        <constraints>\n          <grid row=\"4\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoCreateXML\"/>\n        </properties>\n      </component>\n      <component id=\"5f84\" class=\"javax.swing.JCheckBox\" binding=\"sqlCheck\">\n        <constraints>\n          <grid row=\"5\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoCreateDefinitionSQL\"/>\n        </properties>\n      </component>\n      <component id=\"18e29\" class=\"javax.swing.JCheckBox\" binding=\"voCheck\">\n        <constraints>\n          <grid row=\"6\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"autoCreateSwaggerMo\"/>\n        </properties>\n      </component>\n      <component id=\"2f34\" class=\"javax.swing.JCheckBox\" binding=\"handlerCheck\">\n        <constraints>\n          <grid row=\"7\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"autoCreateHandler\"/>\n        </properties>\n      </component>\n      <component id=\"830e0\" class=\"javax.swing.JCheckBox\" binding=\"controllerCheck\">\n        <constraints>\n          <grid row=\"8\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"autoCreateController\"/>\n        </properties>\n      </component>\n      <component id=\"11b39\" class=\"javax.swing.JCheckBox\" binding=\"formatStyleCheck\">\n        <constraints>\n          <grid row=\"9\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoFormatStyle\"/>\n        </properties>\n      </component>\n      <component id=\"61c8d\" class=\"javax.swing.JCheckBox\" binding=\"detectSQLTimeColumnCheck\">\n        <constraints>\n          <grid row=\"10\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"autoDetectSQLTimeColumn\"/>\n        </properties>\n      </component>\n      <component id=\"ae2f5\" class=\"javax.swing.JCheckBox\" binding=\"mapperBetterThenRepositoryCheck\">\n        <constraints>\n          <grid row=\"11\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <selected value=\"true\"/>\n          <text value=\"mapperBatterThenRepository\"/>\n        </properties>\n      </component>\n      <component id=\"2fe6\" class=\"javax.swing.JLabel\" binding=\"author\">\n        <constraints>\n          <grid row=\"12\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"author\"/>\n        </properties>\n      </component>\n      <component id=\"8b6a7\" class=\"javax.swing.JLabel\" binding=\"apiUrlPrefix\">\n        <constraints>\n          <grid row=\"13\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"apiUrlPrefix\"/>\n        </properties>\n      </component>\n      <component id=\"3430d\" class=\"javax.swing.JLabel\" binding=\"locale\">\n        <constraints>\n          <grid row=\"14\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <text value=\"locale\"/>\n        </properties>\n      </component>\n      <component id=\"c5dcd\" class=\"javax.swing.JLabel\">\n        <constraints>\n          <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <enabled value=\"false\"/>\n          <text value=\"D8ger-帝八哥 \"/>\n        </properties>\n      </component>\n      <component id=\"14fa4\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"mapperExamplePath\">\n        <constraints>\n          <grid row=\"3\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"5b0fe\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"mapperXmlPath\">\n        <constraints>\n          <grid row=\"4\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"ab287\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"sqlPath\">\n        <constraints>\n          <grid row=\"5\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"85eb6\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"voPath\">\n        <constraints>\n          <grid row=\"6\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"4507c\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"handlerPath\">\n        <constraints>\n          <grid row=\"7\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"d6ab5\" class=\"com.intellij.openapi.ui.TextFieldWithBrowseButton\" binding=\"controllerPath\">\n        <constraints>\n          <grid row=\"8\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <editable value=\"true\"/>\n          <text value=\"\"/>\n        </properties>\n      </component>\n      <component id=\"41ed8\" class=\"javax.swing.JTextField\" binding=\"defaultAuthor\">\n        <constraints>\n          <grid row=\"12\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <text value=\"D8ger\"/>\n        </properties>\n      </component>\n      <component id=\"9b716\" class=\"javax.swing.JTextField\" binding=\"defaultUrlPrefix\">\n        <constraints>\n          <grid row=\"13\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"150\" height=\"-1\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <text value=\"/d8ger\"/>\n        </properties>\n      </component>\n      <component id=\"94a9e\" class=\"javax.swing.JComboBox\" binding=\"defaultLocale\">\n        <constraints>\n          <grid row=\"14\" column=\"1\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"2\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <model>\n            <item value=\"ZN\"/>\n            <item value=\"EN\"/>\n          </model>\n        </properties>\n      </component>\n      <component id=\"5f97b\" class=\"javax.swing.JButton\" binding=\"donateButton\" default-binding=\"true\">\n        <constraints>\n          <grid row=\"0\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"1\" hsize-policy=\"1\" anchor=\"4\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties>\n          <background color=\"-2697514\"/>\n          <icon value=\"icons/donate.gif\"/>\n          <inheritsPopupMenu value=\"false\"/>\n          <text value=\"\"/>\n          <toolTipText value=\"Donate via Zhifubao or Wexin\"/>\n        </properties>\n      </component>\n      <hspacer id=\"57b0\">\n        <constraints>\n          <grid row=\"0\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"1\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n      </hspacer>\n    </children>\n  </grid>\n</form>\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSetting.java",
    "content": "package com.xyz.caofancpu.d8ger.setting;\n\nimport com.intellij.ide.BrowserUtil;\nimport com.intellij.openapi.fileChooser.FileChooserDescriptor;\nimport com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.project.ProjectUtil;\nimport com.intellij.openapi.ui.TextBrowseFolderListener;\nimport com.intellij.openapi.ui.TextFieldWithBrowseButton;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport com.intellij.util.ui.JBUI;\nimport com.xyz.caofancpu.d8ger.util.ConstantUtil;\nimport org.jetbrains.annotations.NotNull;\n\nimport javax.swing.*;\nimport java.util.Objects;\n\n/**\n * Setting Form\n *\n * @author D8GER\n */\npublic class D8gerSetting {\n    /**\n     * Current project, this determines the root directory\n     */\n    private Project currentProject;\n\n    /**\n     * File choose descriptor\n     */\n    private FileChooserDescriptor cacheFolderDescriptor;\n    /**\n     * Root panel\n     */\n    private JPanel rootPanel;\n\n    /**\n     * L1\n     */\n    private JCheckBox moCheck;\n    /**\n     * L2\n     */\n    private JCheckBox mapperCheck;\n    /**\n     * L3\n     */\n    private JCheckBox mapperExampleCheck;\n    /**\n     * L4\n     */\n    private JCheckBox mapperXmlCheck;\n    /**\n     * L5\n     */\n    private JCheckBox sqlCheck;\n    /**\n     * L6\n     */\n    private JCheckBox voCheck;\n    /**\n     * L7\n     */\n    private JCheckBox handlerCheck;\n    /**\n     * L8\n     */\n    private JCheckBox controllerCheck;\n    /**\n     * L9\n     */\n    private JCheckBox formatStyleCheck;\n    /**\n     * L10\n     */\n    private JCheckBox detectSQLTimeColumnCheck;\n    /**\n     * L11\n     */\n    private JCheckBox mapperBetterThenRepositoryCheck;\n    /**\n     * L12\n     */\n    private JLabel author;\n    /**\n     * L13\n     */\n    private JLabel apiUrlPrefix;\n    /**\n     * L14\n     */\n    private JLabel locale;\n\n    /**\n     * R1\n     */\n    private TextFieldWithBrowseButton moPath;\n    /**\n     * R2\n     */\n    private TextFieldWithBrowseButton mapperPath;\n    /**\n     * R3\n     */\n    private TextFieldWithBrowseButton mapperExamplePath;\n    /**\n     * R4\n     */\n    private TextFieldWithBrowseButton mapperXmlPath;\n    /**\n     * R5\n     */\n    private TextFieldWithBrowseButton sqlPath;\n    /**\n     * R6\n     */\n    private TextFieldWithBrowseButton voPath;\n    /**\n     * R7\n     */\n    private TextFieldWithBrowseButton handlerPath;\n    /**\n     * R8\n     */\n    private TextFieldWithBrowseButton controllerPath;\n    /**\n     * R12\n     */\n    private JTextField defaultAuthor;\n    /**\n     * R13\n     */\n    private JTextField defaultUrlPrefix;\n    /**\n     * R14\n     */\n    private JComboBox<String> defaultLocale;\n    /**\n     * Donate link button\n     */\n    private JButton donateButton;\n\n    public D8gerSetting(Project project) {\n        this.currentProject = project;\n        initDonate();\n        initTbbListener();\n    }\n\n    private void initTbbListener() {\n        moPath.addBrowseFolderListener(getFolderChooseListener());\n        mapperPath.addBrowseFolderListener(getFolderChooseListener());\n        mapperExamplePath.addBrowseFolderListener(getFolderChooseListener());\n        mapperXmlPath.addBrowseFolderListener(getFolderChooseListener());\n        sqlPath.addBrowseFolderListener(getFolderChooseListener());\n        voPath.addBrowseFolderListener(getFolderChooseListener());\n        handlerPath.addBrowseFolderListener(getFolderChooseListener());\n        controllerPath.addBrowseFolderListener(getFolderChooseListener());\n    }\n\n    private TextBrowseFolderListener getFolderChooseListener() {\n        if (Objects.isNull(cacheFolderDescriptor)) {\n            cacheFolderDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();\n            cacheFolderDescriptor.setTitle(ConstantUtil.FILE_CHOOSE_TITLE);\n            cacheFolderDescriptor.setDescription(ConstantUtil.FILE_CHOOSE_DESCRIPTION);\n            cacheFolderDescriptor.setShowFileSystemRoots(false);\n            cacheFolderDescriptor.withTreeRootVisible(true);\n            cacheFolderDescriptor.setHideIgnored(true);\n            VirtualFile projectDir = ProjectUtil.guessProjectDir(this.currentProject);\n            if (Objects.nonNull(projectDir)) {\n                cacheFolderDescriptor.setRoots(projectDir);\n                cacheFolderDescriptor.setForcedToUseIdeaFileChooser(true);\n            }\n        }\n        return new TextBrowseFolderListener(cacheFolderDescriptor);\n    }\n\n    private void initDonate() {\n        donateButton.setBorder(null);\n        donateButton.setMargin(JBUI.emptyInsets());\n        donateButton.setContentAreaFilled(false);\n        donateButton.addActionListener(e -> BrowserUtil.browse(ConstantUtil.DONATE_CLICK_URL));\n        donateButton.putClientProperty(ConstantUtil.DONATE_BACKGROUND_KEY, rootPanel.getBackground());\n    }\n\n    public JPanel getPanel() {\n        return rootPanel;\n    }\n\n    public JComponent getPreferredFocusedComponent() {\n        return defaultAuthor;\n    }\n\n    public boolean getMoCheck() {\n        return moCheck.isSelected();\n    }\n\n    public void setMoCheck(boolean newStatus) {\n        moCheck.setSelected(newStatus);\n    }\n\n    public boolean getMapperCheck() {\n        return mapperCheck.isSelected();\n    }\n\n    public void setMapperCheck(boolean newStatus) {\n        mapperCheck.setSelected(newStatus);\n    }\n\n    public boolean getMapperExampleCheck() {\n        return mapperExampleCheck.isSelected();\n    }\n\n    public void setMapperExampleCheck(boolean newStatus) {\n        mapperExampleCheck.setSelected(newStatus);\n    }\n\n    public boolean getMapperXmlCheck() {\n        return mapperXmlCheck.isSelected();\n    }\n\n    public void setMapperXmlCheck(boolean newStatus) {\n        mapperXmlCheck.setSelected(newStatus);\n    }\n\n    public boolean getSqlCheck() {\n        return sqlCheck.isSelected();\n    }\n\n    public void setSqlCheck(boolean newStatus) {\n        sqlCheck.setSelected(newStatus);\n    }\n\n    public boolean getVoCheck() {\n        return voCheck.isSelected();\n    }\n\n    public void setVoCheck(boolean newStatus) {\n        voCheck.setSelected(newStatus);\n    }\n\n    public boolean getHandlerCheck() {\n        return handlerCheck.isSelected();\n    }\n\n    public void setHandlerCheck(boolean newStatus) {\n        handlerCheck.setSelected(newStatus);\n    }\n\n    public boolean getControllerCheck() {\n        return controllerCheck.isSelected();\n    }\n\n    public void setControllerCheck(boolean newStatus) {\n        controllerCheck.setSelected(newStatus);\n    }\n\n    public boolean getFormatStyleCheck() {\n        return formatStyleCheck.isSelected();\n    }\n\n    public void setFormatStyleCheck(boolean newStatus) {\n        formatStyleCheck.setSelected(newStatus);\n    }\n\n    public boolean getDetectSQLTimeColumnCheck() {\n        return detectSQLTimeColumnCheck.isSelected();\n    }\n\n    public void setDetectSQLTimeColumnCheck(boolean newStatus) {\n        detectSQLTimeColumnCheck.setSelected(newStatus);\n    }\n\n    public boolean getMapperBetterThenRepositoryCheck() {\n        return mapperBetterThenRepositoryCheck.isSelected();\n    }\n\n    public void setMapperBetterThenRepositoryCheck(boolean newStatus) {\n        mapperBetterThenRepositoryCheck.setSelected(newStatus);\n    }\n\n    @NotNull\n    public String getMoPath() {\n        return moPath.getText();\n    }\n\n    public void setMoPath(@NotNull String newText) {\n        moPath.setText(newText);\n    }\n\n    @NotNull\n    public String getMapperPath() {\n        return mapperPath.getText();\n    }\n\n    public void setMapperPath(@NotNull String newText) {\n        mapperPath.setText(newText);\n    }\n\n    @NotNull\n    public String getMapperExamplePath() {\n        return mapperExamplePath.getText();\n    }\n\n    public void setMapperExamplePath(@NotNull String newText) {\n        mapperExamplePath.setText(newText);\n    }\n\n    @NotNull\n    public String getMapperXmlPath() {\n        return mapperXmlPath.getText();\n    }\n\n    public void setMapperXmlPath(@NotNull String newText) {\n        mapperXmlPath.setText(newText);\n    }\n\n    @NotNull\n    public String getSqlPath() {\n        return sqlPath.getText();\n    }\n\n    public void setSqlPath(@NotNull String newText) {\n        sqlPath.setText(newText);\n    }\n\n    @NotNull\n    public String getVoPath() {\n        return voPath.getText();\n    }\n\n    public void setVoPath(@NotNull String newText) {\n        voPath.setText(newText);\n    }\n\n    @NotNull\n    public String getHandlerPath() {\n        return handlerPath.getText();\n    }\n\n    public void setHandlerPath(@NotNull String newText) {\n        handlerPath.setText(newText);\n    }\n\n    @NotNull\n    public String getControllerPath() {\n        return controllerPath.getText();\n    }\n\n    public void setControllerPath(@NotNull String newText) {\n        controllerPath.setText(newText);\n    }\n\n    @NotNull\n    public String getDefaultAuthor() {\n        return defaultAuthor.getText();\n    }\n\n    public void setDefaultAuthor(@NotNull String newText) {\n        defaultAuthor.setText(newText);\n    }\n\n    @NotNull\n    public String getDefaultUrlPrefix() {\n        return defaultUrlPrefix.getText();\n    }\n\n    public void setDefaultUrlPrefix(@NotNull String newText) {\n        defaultUrlPrefix.setText(newText);\n    }\n\n    @NotNull\n    public String getDefaultLocale() {\n        return defaultLocale.getModel().getSelectedItem().toString();\n    }\n\n    public void setDefaultLocale(@NotNull String newText) {\n        defaultLocale.getModel().setSelectedItem(newText);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSettingsConfigurable.java",
    "content": "package com.xyz.caofancpu.d8ger.setting;\n\nimport com.intellij.openapi.diagnostic.Logger;\nimport com.intellij.openapi.options.Configurable;\nimport com.intellij.openapi.project.Project;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.Nullable;\n\nimport javax.swing.*;\nimport java.util.Objects;\n\n/**\n * D8ger Setting Configurable\n *\n * @author D8GER\n */\npublic class D8gerSettingsConfigurable implements Configurable {\n    private static final Logger LOG = Logger.getInstance(D8gerSettingsConfigurable.class);\n\n    private Project currentProject;\n\n    /**\n     * User custom config result\n     */\n    private D8gerSetting d8gerSetting;\n\n    /**\n     * Must have this construct, and should only inject Project param\n     *\n     * @param currentProject\n     */\n    public D8gerSettingsConfigurable(Project currentProject) {\n        this.currentProject = currentProject;\n    }\n\n    // A default constructor with no arguments is required because this implementation\n    // is registered as an applicationConfigurable EP\n\n    @Nls(capitalization = Nls.Capitalization.Title)\n    @Override\n    public String getDisplayName() {\n        return \"D8gerAutoCode\";\n    }\n\n    @Override\n    public JComponent getPreferredFocusedComponent() {\n        return d8gerSetting.getPreferredFocusedComponent();\n    }\n\n    @Nullable\n    @Override\n    public JComponent createComponent() {\n        LOG.info(\"prepare D8gerAutoCode setting...\");\n        d8gerSetting = new D8gerSetting(this.currentProject);\n        return d8gerSetting.getPanel();\n    }\n\n    @Override\n    public boolean isModified() {\n        D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject);\n        return !Objects.equals(d8gerSetting.getMoPath(), settings.moPath)\n                || !Objects.equals(d8gerSetting.getMapperPath(), settings.mapperPath)\n                || !Objects.equals(d8gerSetting.getMapperExamplePath(), settings.mapperExamplePath)\n                || !Objects.equals(d8gerSetting.getMapperXmlPath(), settings.mapperXmlPath)\n                || !Objects.equals(d8gerSetting.getSqlPath(), settings.sqlPath)\n                || !Objects.equals(d8gerSetting.getVoPath(), settings.voPath)\n                || !Objects.equals(d8gerSetting.getHandlerPath(), settings.handlerPath)\n                || !Objects.equals(d8gerSetting.getControllerPath(), settings.controllerPath)\n                || !Objects.equals(d8gerSetting.getDefaultAuthor(), settings.defaultAuthor)\n                || !Objects.equals(d8gerSetting.getDefaultUrlPrefix(), settings.defaultUrlPrefix)\n                || !Objects.equals(d8gerSetting.getDefaultLocale(), settings.defaultLocale)\n\n                || !Objects.equals(d8gerSetting.getMoCheck(), settings.moCheck)\n                || !Objects.equals(d8gerSetting.getMapperCheck(), settings.mapperCheck)\n                || !Objects.equals(d8gerSetting.getMapperExampleCheck(), settings.mapperExampleCheck)\n                || !Objects.equals(d8gerSetting.getMapperXmlCheck(), settings.mapperXmlCheck)\n                || !Objects.equals(d8gerSetting.getSqlCheck(), settings.sqlCheck)\n                || !Objects.equals(d8gerSetting.getVoCheck(), settings.voCheck)\n                || !Objects.equals(d8gerSetting.getHandlerCheck(), settings.handlerCheck)\n                || !Objects.equals(d8gerSetting.getControllerCheck(), settings.controllerCheck)\n                || !Objects.equals(d8gerSetting.getFormatStyleCheck(), settings.formatStyleCheck)\n                || !Objects.equals(d8gerSetting.getDetectSQLTimeColumnCheck(), settings.detectSQLTimeColumnCheck)\n                || !Objects.equals(d8gerSetting.getMapperBetterThenRepositoryCheck(), settings.mapperBetterThenRepositoryCheck)\n                ;\n    }\n\n    @Override\n    public void apply() {\n        D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject);\n        settings.moCheck = d8gerSetting.getMoCheck();\n        settings.mapperCheck = d8gerSetting.getMapperCheck();\n        settings.mapperExampleCheck = d8gerSetting.getMapperExampleCheck();\n        settings.mapperXmlCheck = d8gerSetting.getMapperXmlCheck();\n        settings.sqlCheck = d8gerSetting.getSqlCheck();\n        settings.voCheck = d8gerSetting.getVoCheck();\n        settings.handlerCheck = d8gerSetting.getHandlerCheck();\n        settings.controllerCheck = d8gerSetting.getControllerCheck();\n        settings.formatStyleCheck = d8gerSetting.getFormatStyleCheck();\n        settings.detectSQLTimeColumnCheck = d8gerSetting.getDetectSQLTimeColumnCheck();\n        settings.mapperBetterThenRepositoryCheck = d8gerSetting.getMapperBetterThenRepositoryCheck();\n\n        settings.moPath = d8gerSetting.getMoPath();\n        settings.mapperPath = d8gerSetting.getMapperPath();\n        settings.mapperExamplePath = d8gerSetting.getMapperExamplePath();\n        settings.mapperXmlPath = d8gerSetting.getMapperXmlPath();\n        settings.sqlPath = d8gerSetting.getSqlPath();\n        settings.voPath = d8gerSetting.getVoPath();\n        settings.handlerPath = d8gerSetting.getHandlerPath();\n        settings.controllerPath = d8gerSetting.getControllerPath();\n        settings.defaultAuthor = d8gerSetting.getDefaultAuthor();\n        settings.defaultUrlPrefix = d8gerSetting.getDefaultUrlPrefix();\n        settings.defaultLocale = d8gerSetting.getDefaultLocale();\n    }\n\n    @Override\n    public void reset() {\n        D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject);\n        d8gerSetting.setMoCheck(settings.moCheck);\n        d8gerSetting.setMapperCheck(settings.mapperCheck);\n        d8gerSetting.setMapperExampleCheck(settings.mapperExampleCheck);\n        d8gerSetting.setMapperXmlCheck(settings.mapperXmlCheck);\n        d8gerSetting.setSqlCheck(settings.sqlCheck);\n        d8gerSetting.setVoCheck(settings.voCheck);\n        d8gerSetting.setHandlerCheck(settings.handlerCheck);\n        d8gerSetting.setControllerCheck(settings.controllerCheck);\n        d8gerSetting.setFormatStyleCheck(settings.formatStyleCheck);\n        d8gerSetting.setDetectSQLTimeColumnCheck(settings.detectSQLTimeColumnCheck);\n        d8gerSetting.setMapperBetterThenRepositoryCheck(settings.mapperBetterThenRepositoryCheck);\n\n        d8gerSetting.setMoPath(settings.moPath);\n        d8gerSetting.setMapperPath(settings.mapperPath);\n        d8gerSetting.setMapperExamplePath(settings.mapperExamplePath);\n        d8gerSetting.setMapperXmlPath(settings.mapperXmlPath);\n        d8gerSetting.setSqlPath(settings.sqlPath);\n        d8gerSetting.setVoPath(settings.voPath);\n        d8gerSetting.setHandlerPath(settings.handlerPath);\n        d8gerSetting.setControllerPath(settings.controllerPath);\n        d8gerSetting.setDefaultAuthor(settings.defaultAuthor);\n        d8gerSetting.setDefaultUrlPrefix(settings.defaultUrlPrefix);\n        d8gerSetting.setDefaultLocale(settings.defaultLocale);\n    }\n\n    @Override\n    public void disposeUIResources() {\n        LOG.info(\"finish D8gerAutoCode setting\");\n        d8gerSetting = null;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/CollectionUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\n\nimport com.google.common.collect.Lists;\nimport lombok.NonNull;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang3.ArrayUtils;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.function.BiFunction;\nimport java.util.function.BinaryOperator;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport java.util.function.Supplier;\nimport java.util.stream.Collectors;\nimport java.util.stream.StreamSupport;\n\n/**\n * Collection tools: https://dzone.com/articles/functional-programming-patterns-with-java-8\n */\npublic class CollectionUtil extends CollectionUtils {\n\n    /**\n     * Find the union of two sets of the same element type, like (a ∪ b),\n     * the container type of the result can be specified\n     *\n     * @param resultColl\n     * @param a\n     * @param b\n     * @param <E>\n     * @param <C>\n     * @return\n     */\n    @SuppressWarnings(\"unchecked\")\n    public static <E, C extends Collection<E>> C union(Supplier<C> resultColl, Collection<E> a, Collection<E> b) {\n        C result = resultColl.get();\n        union(a, b).forEach(item -> result.add((E) item));\n        return result;\n    }\n\n    /**\n     * Find the intersection of two sets of the same element type, like (a ∩ b),\n     * the container type of the result can be specified\n     *\n     * @param resultColl\n     * @param a\n     * @param b\n     * @param <E>\n     * @param <C>\n     * @return\n     */\n    @SuppressWarnings(\"unchecked\")\n    public static <E, C extends Collection<E>> C intersection(Supplier<C> resultColl, Collection<E> a, Collection<E> b) {\n        C result = resultColl.get();\n        intersection(a, b).forEach(item -> result.add((E) item));\n        return result;\n    }\n\n    /**\n     * Find the complement of the intersection of two sets of the same element type, like ((a ∪ b) - (a ∩ b)),\n     * the container type of the result can be specified\n     *\n     * @param resultColl\n     * @param a\n     * @param b\n     * @param <E>\n     * @param <C>\n     * @return\n     */\n    @SuppressWarnings(\"unchecked\")\n    public static <E, C extends Collection<E>> C disjunction(Supplier<C> resultColl, Collection<E> a, Collection<E> b) {\n        C result = resultColl.get();\n        disjunction(a, b).forEach(item -> result.add((E) item));\n        return result;\n    }\n\n    /**\n     * Find the difference between two sets of the same element type, like (a - ( a ∩ b)),\n     * the container type of the result can be specified\n     *\n     * @param resultColl\n     * @param a\n     * @param b\n     * @param <E>\n     * @param <C>\n     * @return\n     */\n    @SuppressWarnings(\"unchecked\")\n    public static <E, C extends Collection<E>> C subtract(Supplier<C> resultColl, Collection<E> a, Collection<E> b) {\n        C result = resultColl.get();\n        subtract(a, b).forEach(item -> result.add((E) item));\n        return result;\n    }\n\n    /**\n     * Sum the specified elements of a list element (fields are numeric)\n     *\n     * @param coll\n     * @param numberValueFunction\n     * @param <F>\n     * @param <T>\n     * @return\n     */\n    public static <F extends Number, T> BigDecimal sum(Collection<T> coll, Function<? super T, ? extends F> numberValueFunction) {\n        double sum = coll.stream()\n                .filter(Objects::nonNull)\n                .map(numberValueFunction)\n                .mapToDouble(Number::doubleValue)\n                .sum();\n        return BigDecimal.valueOf(sum);\n    }\n\n    /**\n     * Average the specified elements of a list element (fields are numeric)\n     *\n     * @param coll\n     * @param numberValueFunction\n     * @param <F>\n     * @param <T>\n     * @return\n     */\n    public static <F extends Number, T> BigDecimal average(Collection<T> coll, Function<? super T, ? extends F> numberValueFunction) {\n        Double average = coll.stream()\n                .filter(Objects::nonNull)\n                .map(numberValueFunction)\n                .collect(Collectors.averagingDouble(Number::doubleValue));\n        return BigDecimal.valueOf(average);\n    }\n\n    /**\n     * Max the specified elements of a list element (fields are numeric)\n     *\n     * @param coll\n     * @param numberValueFunction\n     * @param <F>\n     * @param <T>\n     * @return\n     */\n    public static <F extends Number, T> BigDecimal max(Collection<T> coll, Function<? super T, ? extends F> numberValueFunction) {\n        double max = coll.stream()\n                .filter(Objects::nonNull)\n                .map(numberValueFunction)\n                .mapToDouble(Number::doubleValue)\n                .max()\n                .orElse(0d);\n        return BigDecimal.valueOf(max);\n    }\n\n    /**\n     * Min the specified elements of a list element (fields are numeric)\n     *\n     * @param coll\n     * @param numberValueFunction\n     * @param <F>\n     * @param <T>\n     * @return\n     */\n    public static <F extends Number, T> BigDecimal min(Collection<T> coll, Function<? super T, ? extends F> numberValueFunction) {\n        double min = coll.stream()\n                .filter(Objects::nonNull)\n                .map(numberValueFunction)\n                .mapToDouble(Number::doubleValue)\n                .min()\n                .orElse(0d);\n        return BigDecimal.valueOf(min);\n    }\n\n    /**\n     * Detect duplicates for the specified field of the collection element,\n     * return non-empty duplicate elements\n     *\n     * @param coll\n     * @param mapper\n     * @param <T>\n     * @param <F>\n     * @return\n     */\n    public static <T, F> Set<F> probeRepeatValueSet(Collection<T> coll, Function<? super T, F> mapper) {\n        List<F> elementList = transToList(coll, mapper);\n        List<F> withoutNullElementList = transToList(elementList, Function.identity());\n        Set<F> noRepeatElementSet = new HashSet<>(withoutNullElementList);\n        return subtract(HashSet::new, withoutNullElementList, noRepeatElementSet);\n    }\n\n    /**\n     * Converts a [number] string that is concatenated according to the separator into a list of the specified [number]\n     *\n     * @param source\n     * @param splitSymbol\n     * @param mapper\n     * @param <T>\n     * @return\n     */\n    public static <T> List<T> splitDelimitedStringToList(@NonNull String source, @NonNull String splitSymbol, Function<String, T> mapper) {\n        return transToList(Arrays.asList(source.split(splitSymbol)), mapper);\n    }\n\n    /**\n     * Judge empty or not for Map\n     *\n     * @param sourceMap data source\n     * @return boolean  judge result\n     */\n    public static boolean isEmpty(Map sourceMap) {\n        return Objects.isNull(sourceMap) || sourceMap.isEmpty();\n    }\n\n    public static boolean isNotEmpty(Map sourceMap) {\n        return !isEmpty(sourceMap);\n    }\n\n    /**\n     * Convert to Set, HashSet is used by default\n     *\n     * @param source data source\n     * @param mapper field execution function\n     * @return HashSet\n     */\n    public static <E, R> Set<R> transToSet(Collection<E> source, Function<? super E, ? extends R> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toSet());\n    }\n\n    /**\n     * Convert to List, ArrayList is used by default\n     *\n     * @param source data source\n     * @param mapper field execution function\n     * @return ArrayList\n     */\n    public static <E, R> List<R> transToList(Collection<E> source, Function<? super E, ? extends R> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());\n    }\n\n    /**\n     * Convert to the specified collection, commonly used Set/List，HashSet/ArrayList，LinkedSet/LinkedList\n     *\n     * @param resultColl Specify a collection container\n     * @param source     data source\n     * @param mapper     field execution function\n     * @return C\n     */\n    public static <E, R, C extends Collection<R>> C transToCollection(Supplier<C> resultColl, Collection<E> source, Function<? super E, ? extends R> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toCollection(resultColl));\n    }\n\n    /**\n     * Two layers of Nested Collection are collapsed and tiled into a List, and ArrayList is used by default\n     * Multi-level nesting can be completed by repeatedly calling this method\n     *\n     * @param source Two levels of nested List data sources\n     * @param mapper Outer element gets execution function of inner collection\n     * @return List collected after tiling\n     */\n    public static <E, R> List<R> transToListWithFlatMap(Collection<E> source, Function<? super E, ? extends List<R>> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).flatMap(List::stream).collect(Collectors.toList());\n    }\n\n    /**\n     * Two layers of Nested Collection are collapsed and tiled into a List, and HashSet is used by default\n     * Multi-level nesting can be completed by repeatedly calling this method\n     *\n     * @param source Two levels of nested Set data sources\n     * @param mapper Outer element gets execution function of inner collection\n     * @return Set collected after tiling\n     */\n    public static <E, R> Set<R> transToSetWithFlatMap(Collection<E> source, Function<? super E, ? extends List<R>> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).flatMap(List::stream).collect(Collectors.toSet());\n    }\n\n    /**\n     * Perform filtering based on element fields meeting certain conditions, and convert to Set\n     *\n     * @param coll      data source\n     * @param predicate filter conditions\n     * @param mapper    functions that compute the filtered out elements\n     * @return HashSet\n     */\n    public static <F, T> Set<F> filterAndTransSet(Collection<T> coll, Predicate<? super T> predicate, Function<? super T, ? extends F> mapper) {\n        return coll.stream().filter(Objects::nonNull).filter(predicate).map(mapper).collect(Collectors.toSet());\n    }\n\n    /**\n     * Remove the element fields that meet the condition removePredicate and convert to Set.\n     * This method is opposite with {@link #filterAndTransSet}, so their results are complementary\n     *\n     * @param coll            data source\n     * @param removePredicate filter conditions\n     * @param mapper          functions that compute the filtered out elements\n     * @return HashSet\n     */\n    public static <F, T> Set<F> removeAndTransSet(Collection<T> coll, Predicate<? super T> removePredicate, Function<? super T, ? extends F> mapper) {\n        return coll.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toSet());\n    }\n\n    /**\n     * Perform filtering based on element fields meeting certain conditions, and convert to List.\n     *\n     * @param coll      data source\n     * @param predicate filter conditions\n     * @param mapper    functions that compute the filtered out elements\n     * @return ArrayList\n     */\n    public static <F, T> List<F> filterAndTransList(Collection<T> coll, Predicate<? super T> predicate, Function<? super T, ? extends F> mapper) {\n        return coll.stream().filter(Objects::nonNull).filter(predicate).map(mapper).collect(Collectors.toList());\n    }\n\n    /**\n     * Perform filtering based on the element field meeting certain conditions, and convert to List.\n     * This method is opposite with {@link #filterAndTransList}, so their results are complementary\n     *\n     * @param coll            data source\n     * @param removePredicate filter conditions\n     * @param mapper          functions that compute the filtered out elements\n     * @return ArrayList\n     */\n    public static <F, T> List<F> removeAndTransList(Collection<T> coll, Predicate<? super T> removePredicate, Function<? super T, ? extends F> mapper) {\n        return coll.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toList());\n    }\n\n    /**\n     * Perform filtering based on the element field meeting certain conditions,\n     * and convert to the specified collection\n     *\n     * @param resultColl       results collection container\n     * @param sourceColl       data source\n     * @param survivePredicate retention conditions\n     * @param mapper           functions that compute the filtered out elements\n     * @return R\n     */\n    public static <T, F, R extends Collection<F>> R filterAndTransColl(Supplier<R> resultColl, Collection<T> sourceColl, Predicate<? super T> survivePredicate, Function<? super T, ? extends F> mapper) {\n        return sourceColl.stream().filter(Objects::nonNull).filter(survivePredicate).map(mapper).collect(Collectors.toCollection(resultColl));\n    }\n\n    /**\n     * Remove the element fields that meet the condition removePredicate and convert to List.\n     * This method is opposite with {@link #filterAndTransColl}, so their results are complementary\n     *\n     * @param resultColl      results collection container\n     * @param sourceColl      data source\n     * @param removePredicate elimination conditions\n     * @param mapper          functions that compute the filtered out elements\n     * @return R\n     */\n    public static <T, F, R extends Collection<F>> R removeAndTransColl(Supplier<R> resultColl, Collection<T> sourceColl, Predicate<? super T> removePredicate, Function<? super T, ? extends F> mapper) {\n        return sourceColl.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toCollection(resultColl));\n    }\n\n\n    /**\n     * Get a set of fields of an element, and remove duplicates\n     *\n     * @param source data source\n     * @param mapper field execution function\n     * @return\n     */\n    public static <E, R> List<R> distinctList(Collection<E> source, Function<? super E, ? extends R> mapper) {\n        return source.stream().filter(Objects::nonNull).map(mapper).distinct().collect(Collectors.toList());\n    }\n\n    /**\n     * Deduplication according to the specified field in the collection element,\n     * return the deduplicated element collection\n     *\n     * @param coll               data source\n     * @param distinctComparator Element field comparator (may be a joint comparator for multiple fields)\n     * @return Deduplicated original element collection\n     */\n    public static <T> List<T> distinctListByField(Collection<T> coll, Comparator<T> distinctComparator) {\n        if (isEmpty(coll)) {\n            return Collections.emptyList();\n        }\n        return coll.stream()\n                .filter(Objects::nonNull)\n                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(distinctComparator)), ArrayList::new));\n    }\n\n    /**\n     * In order to avoid data loss, the bottom layer of the Steam API makes more rigid requirements for Collectors.toMap\n     * 1.methods named 'toMap' are not allow duplicate keys first,\n     * so you need to pay attention to using the KEY field when grouping\n     * 2.not allow null VALUE either\n     *\n     * Therefore, please pay attention to the above two when using the following named '*ToMap' method,\n     * and named '*ToMapEnhance' method allows the key to be duplicated and enables the new value to replace the old value\n     *\n     */\n\n    /**\n     * Group conversion to Map<K, List <V>>, support key function, value function, HashMap<K, ArrayList<V>> is used by default\n     *\n     * @param source\n     * @param kFunction\n     * @return\n     */\n    public static <E, K> Map<K, List<E>> groupIndexToMap(Collection<E> source, Function<? super E, ? extends K> kFunction) {\n        return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction));\n    }\n\n    /**\n     * Group conversion to Map<K, List <V>>, support key function, value function, HashMap<K, ArrayList<V>> is used by default\n     *\n     * @param source\n     * @param kFunction\n     * @param vFunction\n     * @param <E>\n     * @param <K>\n     * @param <V>\n     * @return\n     */\n    public static <E, K, V> Map<K, List<V>> groupIndexToMap(Collection<E> source, Function<? super E, ? extends K> kFunction, Function<? super E, ? extends V> vFunction) {\n        return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, HashMap::new, Collectors.mapping(vFunction, Collectors.toList())));\n    }\n\n    /**\n     * Group conversion to specified Map<K, specified List<V>>, such as TreeMap<K, LinkedList<V>> | LinkedHashMap<K, LinkedList<V>>\n     *\n     * @param mapColl\n     * @param source\n     * @param kFunction\n     * @return\n     */\n    public static <E, K, M extends Map<K, List<E>>> M groupIndexToMap(Supplier<M> mapColl, Collection<E> source, Function<? super E, ? extends K> kFunction) {\n        return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, mapColl, Collectors.toList()));\n    }\n\n    /**\n     * Group conversion to specified Map<K, specified List<V>>, such as TreeMap<K, LinkedList<V>> | LinkedHashMap<K, LinkedList<V>>\n     *\n     * @param mapColl\n     * @param vColl\n     * @param source\n     * @param kFunction\n     */\n    public static <E, K, M extends Map<K, C>, C extends Collection<E>> M groupIndexToMap(Supplier<M> mapColl, Supplier<C> vColl, Collection<E> source, Function<? super E, ? extends K> kFunction) {\n        return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, mapColl, Collectors.toCollection(vColl)));\n    }\n\n    /**\n     * Group conversion to specified Map<K, specified List<V>>, such as TreeMap<K, LinkedList<V>> | LinkedHashMap<K, LinkedList<V>>,\n     * and can calculate (convert) the original array elements into other objects\n     *\n     * @param mapColl\n     * @param vColl\n     * @param source\n     * @param kGroupFunction\n     * @param vFunction\n     * @return\n     */\n    public static <E, K, V, M extends Map<K, C>, C extends Collection<V>> M groupIndexToMap(Supplier<M> mapColl, Supplier<C> vColl, Collection<E> source, Function<? super E, ? extends K> kGroupFunction, Function<? super E, ? extends V> vFunction) {\n        return source.stream().filter(Objects::nonNull).collect(\n                Collectors.groupingBy(kGroupFunction, mapColl, Collectors.mapping(vFunction, Collectors.toCollection(vColl))));\n    }\n\n    /**\n     * Convert to Map<Key, Value>\n     *\n     * @param values\n     * @param kFunction\n     * @return\n     */\n    public static <E, K> Map<K, E> transToMap(@NonNull Iterable<E> values, Function<? super E, ? extends K> kFunction) {\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, Function.identity()));\n    }\n\n    /**\n     * Convert to Map-Value, any duplicate key will throw exception\n     *\n     * @param mapColl\n     * @param values\n     * @param kFunction\n     * @return\n     */\n    public static <E, K, M extends Map<K, E>> M transToMap(Supplier<M> mapColl, @NonNull Iterable<E> values, Function<? super E, ? extends K> kFunction) {\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, Function.identity(), nonDuplicateKey(), mapColl));\n    }\n\n\n    /**\n     * Convert to Map<Key, Value>, allow duplicate key\n     *\n     * @param mapColl\n     * @param values\n     * @param kFunction\n     * @return\n     */\n    public static <E, K, M extends Map<K, E>> M transToMapEnhance(Supplier<M> mapColl, @NonNull Iterable<E> values, Function<? super E, ? extends K> kFunction) {\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, Function.identity(), enableNewOnDuplicateKey(), mapColl));\n    }\n\n\n    /**\n     * Convert to Map<Key, Value>\n     *\n     * @param values\n     * @param kFunction\n     * @param vFunction\n     * @return\n     */\n    public static <E, K, V> Map<K, V> transToMap(@NonNull Iterable<E> values, Function<? super E, ? extends K> kFunction, Function<? super E, ? extends V> vFunction) {\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, vFunction));\n    }\n\n\n    /**\n     * Convert to Map<Key, Value>, any duplicate key will throw exception\n     *\n     * @param mapColl\n     * @param values\n     * @param kFunction\n     * @param vFunction\n     * @return\n     */\n    public static <E, K, V, M extends Map<K, V>> M transToMap(Supplier<M> mapColl, @NonNull Iterable<E> values, Function<? super E, ? extends K> kFunction, Function<? super E, ? extends V> vFunction) {\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, vFunction, nonDuplicateKey(), mapColl));\n    }\n\n    /**\n     * Convert two nested Lists into Map<K, List<V>>, and superimpose List<V> according to K\n     *\n     * @param mapColl\n     * @param values\n     * @param kFunction\n     * @param vFunction\n     * @return\n     */\n    public static <E, K, V, M extends Map<K, List<V>>> M transToMapByMerge(Supplier<M> mapColl, Iterable<E> values, Function<? super E, K> kFunction, Function<? super E, List<V>> vFunction) {\n        if (Objects.isNull(values)) {\n            return mapColl.get();\n        }\n        return StreamSupport.stream(values.spliterator(), Boolean.FALSE)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(kFunction, vFunction, (list1, list2) -> {\n                    list1.addAll(list2);\n                    return list1;\n                }, mapColl));\n\n    }\n\n    /**\n     * Splicing array elements into strings according to the specified delimiter\n     *\n     * @param arr\n     * @param separator\n     * @return\n     */\n    public static String join(Object[] arr, String separator) {\n        if (ArrayUtils.isEmpty(arr)) {\n            return StringUtils.EMPTY;\n        }\n        return join(Arrays.asList(arr), separator);\n    }\n\n    /**\n     * Splicing array elements into strings according to the specified delimiter\n     *\n     * @param coll\n     * @param separator\n     * @return\n     */\n    public static <T> String join(Collection<T> coll, String separator) {\n        if (CollectionUtil.isEmpty(coll)) {\n            return StringUtils.EMPTY;\n        }\n        if (Objects.isNull(separator)) {\n            separator = StringUtils.EMPTY;\n        }\n        return coll.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(separator));\n    }\n\n    /**\n     * Sorting Map\n     *\n     * @param sourceMap\n     * @param comparator\n     * @param <K>\n     * @param <V>\n     * @return\n     */\n    public static <K, V extends Comparable<V>> LinkedHashMap<K, V> sortedMapByValue(Map<K, V> sourceMap, Comparator<? super Entry<K, V>> comparator) {\n        if (isEmpty(sourceMap)) {\n            return new LinkedHashMap<>(2, 0.5F, Boolean.FALSE);\n        }\n        List<Entry<K, V>> entryList = sourceMap.entrySet().stream().sorted(comparator).collect(Collectors.toList());\n        return transToMap(LinkedHashMap::new, entryList, Entry::getKey, Entry::getValue);\n    }\n\n    /**\n     * Find elements in the List according to the specified field function,\n     * if any one is found, it will be returned, or null if it is not found.\n     *\n     * @param coll\n     * @param function\n     * @param value\n     * @return\n     */\n    public static <T, F> T findAny(Collection<T> coll, Function<? super T, ? extends F> function, @NonNull F value) {\n        return coll.stream().filter(item -> value.equals(function.apply(item))).findAny().orElse(null);\n    }\n\n    /**\n     * Find a value in a array, normally used in Enum class\n     *\n     * @param source\n     * @param function\n     * @param value\n     * @param <T>\n     * @param <F>\n     * @return\n     */\n    public static <T, F> T findAnyInArrays(T[] source, Function<? super T, ? extends F> function, @NonNull F value) {\n        return findAny(Arrays.asList(source), function, value);\n    }\n\n    /**\n     * Find elements in a list according to a custom field function,\n     * return the first element found or null if not found\n     *\n     * @param coll\n     * @param function\n     * @param value\n     * @return\n     */\n    public static <T, F> T findFirst(Collection<T> coll, Function<? super T, ? extends F> function, @NonNull F value) {\n        return coll.stream().filter(item -> value.equals(function.apply(item))).findFirst().orElse(null);\n    }\n\n    /**\n     * Finds elements according to specified conditions,\n     * return the first element found or null if not found\n     *\n     * @param coll\n     * @param predicate\n     * @return\n     */\n    public static <T> T findFirst(Collection<T> coll, Predicate<? super T> predicate) {\n        return coll.stream().filter(predicate).findFirst().orElse(null);\n    }\n\n    /**\n     * Find all elements from the list based on unique field values\n     *\n     * @param coll\n     * @param function\n     * @param value\n     * @return\n     */\n    public static <T, F> List<T> findAll(Collection<T> coll, Function<? super T, ? extends F> function, @NonNull F value) {\n        if (isEmpty(coll)) {\n            return Lists.newArrayList();\n        }\n        return coll.stream()\n                .filter(Objects::nonNull)\n                .filter(item -> value.equals(function.apply(item)))\n                .collect(Collectors.toList());\n    }\n\n    /**\n     * Determine and find all elements existed in the list\n     *\n     * @param coll\n     * @param predicate\n     * @return\n     */\n    public static <T> List<T> findAll(Collection<T> coll, Predicate<? super T> predicate) {\n        return coll.stream().filter(predicate).collect(Collectors.toList());\n    }\n\n    /**\n     * Determine if an element has at least one value in the list,\n     * and return immediately if it exists\n     *\n     * @param coll\n     * @param function\n     * @param value\n     * @return\n     */\n    public static <T, F> boolean existAtLeastOne(Collection<T> coll, Function<? super T, ? extends F> function, @NonNull F value) {\n        return coll.stream().anyMatch(item -> value.equals(function.apply(item)));\n    }\n\n    /**\n     * Determine if an element exists in the list\n     *\n     * @param coll\n     * @param function\n     * @param value\n     * @return\n     */\n    public static <T, F> boolean exist(Collection<T> coll, Function<? super T, ? extends F> function, @NonNull F value) {\n        return coll.stream().allMatch(item -> value.equals(function.apply(item)));\n    }\n\n    /**\n     * Determine if an element exists in the list\n     *\n     * @param coll\n     * @param predicate\n     * @return\n     */\n    public static <T> boolean exist(Collection<T> coll, Predicate<? super T> predicate) {\n        T existFirstOne = coll.stream().filter(predicate).findFirst().orElse(null);\n        return Objects.nonNull(existFirstOne);\n    }\n\n    /**\n     * Map key-value pair inversion,\n     * for example,\n     * { examA : [stu1, stu2, stu3], examB: [stu1, stu2] }\n     * ⬇\n     * {stu1 : [examA, examB], stu2 : [examA, examB], stu3 : [examA]}\n     *\n     * @param sourceMap\n     * @param kFunction\n     * @param vFunction\n     * @return\n     */\n    public static <E1, E2, K1, K2> Map<K2, List<E2>> reverseKV(@NonNull Map<K1, List<E1>> sourceMap, Function<? super K1, ? extends E2> kFunction, Function<? super E1, ? extends K2> vFunction) {\n        Map<K2, List<E2>> aux = new HashMap<>();\n        sourceMap.entrySet().stream()\n                .filter(Objects::nonNull)\n                .forEach(entry -> entry.getValue().stream()\n                        .filter(Objects::nonNull)\n                        .forEach(v -> aux.computeIfAbsent(vFunction.apply(v), init -> new ArrayList<>()).add(kFunction.apply(entry.getKey())))\n                );\n        return aux;\n    }\n\n    /**\n     * Map key-value pair inversion, support return a custom collection container,\n     * for example, return LinkedHashMap<K, LinkedList<V>\n     * <p>\n     * Map<k1, Coll_1<v1>>  ==>  Map<k2, Coll_1<v2>>\n     * kFunction.apply(k1) ==> v2\n     * vFunction.apply(v1) ==> k2\n     *\n     * @param mapColl\n     * @param vColl\n     * @param sourceMap\n     * @param kFunction\n     * @param vFunction\n     * @return\n     */\n    public static <V1, V2, K1, K2, C1 extends Collection<V1>, C2 extends Collection<V2>, M1 extends Map<K1, C1>, M2 extends Map<K2, C2>>\n    M2 reverseKV(Supplier<M2> mapColl, Supplier<C2> vColl, @NonNull M1 sourceMap, Function<? super K1, ? extends V2> kFunction, Function<? super V1, ? extends K2> vFunction) {\n        M2 aux = mapColl.get();\n        sourceMap.entrySet().stream()\n                .filter(Objects::nonNull)\n                .forEach(entry -> entry.getValue().stream()\n                        .filter(Objects::nonNull)\n                        .forEach(v -> aux.computeIfAbsent(vFunction.apply(v), init -> vColl.get()).add(kFunction.apply(entry.getKey())))\n                );\n        return aux;\n    }\n\n    /**\n     * For complex maps, find the set of key-value pairs for the key matching function\n     * Returns null if the matching function conditions are not met\n     *\n     * @param srcMap\n     * @param kFunction\n     * @param value\n     * @return\n     */\n    public static <K, V, T> List<Entry<K, V>> findInMap(Map<K, V> srcMap, Function<? super K, ? extends T> kFunction, @NonNull T value) {\n        if (isEmpty(srcMap)) {\n            return null;\n        }\n        return srcMap.entrySet().stream()\n                .filter(Objects::nonNull)\n                .map(entry -> {\n                    if (value.equals(kFunction.apply(entry.getKey()))) {\n                        return entry;\n                    }\n                    return null;\n                })\n                .filter(Objects::nonNull)\n                .collect(Collectors.toList());\n    }\n\n    /**\n     * For complex Maps, find the key-value pairs of the key matching function, and only take one\n     * Returns null if the matching function conditions are not met\n     *\n     * @param srcMap\n     * @param kFunction\n     * @param value\n     * @return\n     */\n    public static <K, V, T> Entry<K, V> findOneInMap(Map<K, V> srcMap, Function<? super K, ? extends T> kFunction, @NonNull T value) {\n        if (isEmpty(srcMap)) {\n            return null;\n        }\n        return srcMap.entrySet().stream()\n                .filter(Objects::nonNull)\n                .filter(entry -> value.equals(kFunction.apply(entry.getKey())))\n                .findAny()\n                .get();\n    }\n\n    /**\n     * For complex Maps, find the key-value pairs of the key matching function, and only take one\n     * Returns null if the matching function conditions are not met\n     *\n     * @param srcMap\n     * @param kFunction\n     * @param value\n     * @return\n     */\n    public static <K, V, T> V findOneValue(Map<K, V> srcMap, Function<? super K, ? extends T> kFunction, @NonNull T value) {\n        Entry<K, V> resultEntry = findOneInMap(srcMap, kFunction, value);\n        return Objects.isNull(resultEntry) ? null : resultEntry.getValue();\n    }\n\n    /**\n     * Returns a merge function, suitable for use in\n     * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or\n     * throws {@code IllegalStateException}.  This can be used to enforce the\n     * assumption that the elements being collected are distinct.\n     *\n     * @param <T> the type of input arguments to the merge function\n     * @return a merge function which always throw {@code IllegalStateException}\n     */\n    private static <T> BinaryOperator<T> nonDuplicateKey() {\n        return (u, v) -> {\n            throw new IllegalStateException(String.format(\"Duplicate keys are not allowed when converting Map: [%s]\", u));\n        };\n    }\n\n    private static <T> BinaryOperator<T> enableNewOnDuplicateKey() {\n        return (oldValue, newValue) -> newValue;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/ConstantUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.util.Collections;\n\n/**\n * Common symbols\n *\n * @author caofanCPU\n */\npublic class ConstantUtil {\n\n    /**\n     * Enum name suffix\n     */\n    public static final String ENUM_SUFFIX = \"Enum\";\n\n    /**\n     * Comma\n     */\n    public static final String ENGLISH_COMMA = \",\";\n\n    /**\n     * Chinese Comma\n     */\n    public static final String CHINESE_COMMA = \"，\";\n\n    /**\n     * English colon\n     */\n    public static final String ENGLISH_COLON = \":\";\n\n    /**\n     * English double quotes\n     */\n    public static final String ENGLISH_DOUBLE_QUOTES = \"\\\"\";\n    /**\n     * Escapes\n     */\n    public static final String ESCAPES = \"\\\\\";\n\n    /**\n     * Double Escapes, normally used in regex\n     */\n    public static final String DOUBLE_ESCAPES = \"\\\\\\\\\";\n\n    /**\n     * Period\n     */\n    public static final String ENGLISH_FULL_STOP = \".\";\n\n    /**\n     * Fill in the blank placeholder: two dashes\n     */\n    public static final String FILL_EMPTY_PLACE_HOLDER = \"--\";\n\n    /**\n     * Joiner: single dash\n     */\n    public static final String JOINER = \"-\";\n\n    /**\n     * Underline\n     */\n    public static final String UNDERLINE = \"_\";\n\n    /**\n     * Empty string\n     */\n    public static final String EMPTY = StringUtils.EMPTY;\n\n    /**\n     * Single space character\n     */\n    public static final String SPACE = StringUtils.SPACE;\n\n    /**\n     * Tab: Two spaces\n     */\n    public static final String MINI_TAB = CollectionUtil.join(Collections.nCopies(2, SPACE), EMPTY);\n\n    /**\n     * Tab: Four spaces\n     */\n    public static final String TAB = CollectionUtil.join(Collections.nCopies(2, MINI_TAB), EMPTY);\n\n    /**\n     * Origin Tab character\n     */\n    public static final String ORIGIN_TAB = \"\\t\";\n\n    /**\n     * Double Tabs\n     */\n    public static final String DOUBLE_TAB = TAB + TAB;\n\n    /**\n     * Triple Tabs\n     */\n    public static final String TRIPLE_TAB = DOUBLE_TAB + TAB;\n\n    /**\n     * Quaternary Tabs\n     */\n    public static final String QUATERNARY_TAB = TRIPLE_TAB + TAB;\n\n    /**\n     * Penta Tabs\n     */\n    public static final String PENTA_TAB = QUATERNARY_TAB + TAB;\n\n    /**\n     * Windows OS linebreak character\n     */\n    public static final String WINDOWS_NEXT_LINE = \"\\r\\n\";\n\n    /**\n     * Newline character\n     */\n    public static final String NEXT_LINE = \"\\n\";\n\n    /**\n     * Double newlines\n     */\n    public static final String DOUBLE_NEXT_LINE = NEXT_LINE + NEXT_LINE;\n\n    /**\n     * Semicolon\n     */\n    public static final String ENGLISH_SEMICOLON = \";\";\n\n    /**\n     * Java file extension\n     */\n    public static final String JAVA_FILE_SUFFIX = \".java\";\n\n    /**\n     * xml file extension\n     */\n    public static final String XML_FILE_SUFFIX = \".xml\";\n\n    /**\n     * sql file extension\n     */\n    public static final String SQL_FILE_SUFFIX = \".sql\";\n\n    /**\n     * SQL ID column\n     */\n    public static final String SQL_ID = \"id\";\n\n    /**\n     * SQL create time column\n     */\n    public static final String SQL_CREATE_TIME = \"createTime\";\n\n    /**\n     * ZN SQL create time\n     */\n    public static final String ZN_SQL_CREATE_TIME = \"创建时间\";\n\n    /**\n     * SQL update time column\n     */\n    public static final String SQL_UPDATE_TIME = \"updateTime\";\n\n    /**\n     * ZN SQL update time\n     */\n    public static final String ZN_SQL_UPDATE_TIME = \"更新时间\";\n\n    /**\n     * Mo name suffix\n     */\n    public static final String MO_SUFFIX = \"Mo\";\n\n    /**\n     * SwaggerMo name suffix\n     */\n    public static final String SWAGGER_MO_SUFFIX = \"Vo\";\n\n    /**\n     * MoMapper name suffix\n     */\n    public static final String MO_MAPPER_NAME_SUFFIX = \"Mapper\";\n\n    /**\n     * MoExample name suffix\n     */\n    public static final String MO_EXAMPLE_NAME_SUFFIX = \"Example\";\n\n    /**\n     * MoHandler name suffix\n     */\n    public static final String MO_HANDLER_SUFFIX = \"Handler\";\n\n    /**\n     * MoController name suffix\n     */\n    public static final String MO_CONTROLLER_NAME_SUFFIX = \"Controller\";\n\n    /**\n     * Auto code file directory name\n     */\n    public static final String GENERATE_DIR = \"D8AutoCode\";\n\n    /**\n     * Field access Default modifier\n     */\n    public static final String DEFAULT_ACCESS_MODIFIER = \"private\";\n\n    /**\n     * Notification group view ID\n     */\n    public static final String NOTIFICATION_GROUP_VIEW_ID = \"xtools\";\n\n    /**\n     * Config file name\n     */\n    public static final String D8GER_CONFIG_FILE_NAME = \"d8ger.properties\";\n\n    /**\n     * Author config key\n     */\n    public static final String CONFIG_AUTHOR_KEY = \"author\";\n\n    /**\n     * Default author name\n     */\n    public static final String DEFAULT_AUTHOR = \"D8ger\";\n\n    /**\n     * Interface url prefix config key\n     */\n    public static final String CONFIG_API_URL_PREFIX_KEY = \"apiUrlPrefix\";\n\n    /**\n     * Default interface url prefix\n     */\n    public static final String DEFAULT_API_URL_PREFIX = \"/d8gerAutoCoding\";\n\n    /**\n     * Language config key\n     */\n    public static final String CONFIG_LANGUAGE_KEY = \"locale\";\n\n    /**\n     * Default config language, EN(English)\n     */\n    public static final String DEFAULT_CONFIG_LANGUAGE = \"EN\";\n\n    /**\n     * Optional config language, ZN(Chinese Simplified)\n     */\n    public static final String OPTIONAL_CONFIG_LANGUAGE = \"ZN\";\n\n    /**\n     * Pagination number field name\n     */\n    public static final String PAGE_NUM_NAME = \"pageNum\";\n\n    /**\n     * Pagination size field name\n     */\n    public static final String PAGE_SIZE_NAME = \"pageSize\";\n\n    /**\n     * Spring MVC mapper with annotation @Repository\n     */\n    public static final Pair<String, String> MVC_MAPPER = Pair.of(\"org.springframework.stereotype.Repository\", \"@Repository\");\n\n    /**\n     * SpringBoot mapper with annotation @Mapper\n     */\n    public static final Pair<String, String> BOOT_MAPPER = Pair.of(\"org.apache.ibatis.annotations.Mapper\", \"@Mapper\");\n\n    public static final String FILE_CHOOSE_TITLE = \"Please Select a Generate Directory\";\n\n    public static final String FILE_CHOOSE_DESCRIPTION = \"The file will be generated by D8gerAutoCode here\";\n\n    public static final String DONATE_BACKGROUND_KEY = \"JButton.backgroundColor\";\n\n    public static final String DONATE_CLICK_URL = \"http://www.debuggerpowerzcy.top/home/2020/09/05/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\";\n\n    public static final String PLUGIN_ID = \"com.xyz.caofancpu.D8gerAutoCode\";\n\n    public static final String RENDER_TITLE = \"D8ger•帝八哥\";\n\n    /**\n     * Greater\n     */\n    public static final String GREATER = \">\";\n\n    /**\n     * Less then\n     */\n    public static final String LESS_THEN = \"<\";\n\n    /**\n     * English mid left bracket\n     */\n    public static final String ENGLISH_MID_LEFT_BRACKET = \"[\";\n\n    /**\n     * English mid right bracket\n     */\n    public static final String ENGLISH_MID_RIGHT_BRACKET = \"]\";\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/DateUtil.java",
    "content": "/*\n * Copyright 2016-2020 the original author\n *\n * @D8GER(https://github.com/caofanCPU).\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.xyz.caofancpu.d8ger.util;\n\nimport lombok.NonNull;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.time.Instant;\nimport java.time.LocalDateTime;\nimport java.time.ZoneOffset;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Objects;\nimport java.util.regex.Pattern;\n\n\n/**\n * LocalDateTime-Data converter and handler\n *\n * @author D8GER\n */\n@Slf4j\npublic class DateUtil {\n    public static final Pattern DATE_TIME_REGEX = Pattern.compile(\"(?:[Tt])+\");\n    public final static String DATETIME_FORMAT_SIMPLE = \"yyyy-MM-dd HH:mm:ss\";\n    public final static String DATETIME_FORMAT_DETAIL = \"yyyy-MM-dd HH:mm:ss:SSS\";\n    public final static String DATETIME_FORMAT_DETAIL_DOT = \"yyyy-MM-dd HH:mm:ss.SSS\";\n    public final static String DATETIME_FORMAT_CN = \"yyyy年MM月dd日HH时mm分ss秒\";\n\n    public final static ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of(\"+8\");\n\n    /**\n     * Long to LocalDateTime\n     */\n    public static LocalDateTime toLocalDateTime(@NonNull Long milliSeconds) {\n        return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliSeconds), DEFAULT_ZONE_OFFSET);\n    }\n\n    /**\n     * String of date and time, for example, 2020-09-14 15:45:57 convert to Long: milliseconds\n     *\n     * @param dateTimeStr\n     * @return\n     */\n    public static Long parseStandardMilliSeconds(String dateTimeStr) {\n        return parseStandardDateTime(dateTimeStr).toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli();\n    }\n\n    /**\n     * String of date and time, for example, 2020-09-14 15:45:57 convert to LocalDateTime\n     *\n     * @param dateTimeStr\n     * @return\n     */\n    public static LocalDateTime parseStandardDateTime(String dateTimeStr) {\n        return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(DATETIME_FORMAT_SIMPLE));\n    }\n\n    /**\n     * Long to LocalDateTimeString\n     */\n    public static String enhanceToLocalDateTime(@NonNull Long milliSeconds) {\n        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(milliSeconds), DEFAULT_ZONE_OFFSET);\n        return localDateTime.format(DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL_DOT));\n    }\n\n    /**\n     * String of date and time, convert to String: milliseconds\n     * for example:\n     * 2020-09-14 15:45:57\n     * 2020-09-14T15:45:57\n     * 2020-09-14t15:45:57\n     * 2020-09-14 15:45:57.007\n     * 2020-09-14 15:45:57:007\n     * 2020年09月14日15时45分57秒\n     *\n     * @param dateTimeStr\n     * @return\n     */\n    public static String enhanceParseMilliSeconds(String dateTimeStr) {\n        if (StringUtils.isBlank(dateTimeStr)) {\n            return dateTimeStr;\n        }\n        String originWord = dateTimeStr.replaceAll(DATE_TIME_REGEX.pattern(), ConstantUtil.SPACE);\n        LocalDateTime parse = null;\n        try {\n            parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_SIMPLE));\n        } catch (Exception e) {\n            try {\n                parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL));\n            } catch (Exception exception) {\n                try {\n                    parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL_DOT));\n                } catch (Exception ex) {\n                    parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_CN));\n                }\n            }\n        }\n        return Objects.nonNull(parse) ? String.valueOf(parse.toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli()) : dateTimeStr;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/IdeaPlatformFileTreeUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport com.intellij.ide.highlighter.JavaFileType;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.vfs.LocalFileSystem;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport com.intellij.psi.PsiClass;\nimport com.intellij.psi.PsiDirectory;\nimport com.intellij.psi.PsiElement;\nimport com.intellij.psi.PsiFile;\nimport com.intellij.psi.PsiFileFactory;\nimport com.intellij.psi.PsiJavaFile;\nimport com.intellij.psi.codeStyle.CodeStyleManager;\nimport com.intellij.psi.impl.file.PsiDirectoryFactory;\nimport com.intellij.psi.search.GlobalSearchScope;\nimport com.intellij.psi.search.PsiShortNamesCache;\nimport lombok.NonNull;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.Predicate;\n\n/**\n * IDEA platform file system operation tools\n *\n * @author caofanCPU\n **/\npublic class IdeaPlatformFileTreeUtil {\n\n    /**\n     * Create a file forcibly, delete the source file before creating it\n     *\n     * @param psiDirectory\n     * @param project\n     * @param dotFileName  for example: a.java | b.xml | c.sql | d.txt | e.mp3\n     * @param content\n     * @return\n     */\n    public static PsiJavaFile forceCreateJavaFile(@NonNull PsiDirectory psiDirectory, @NonNull Project project, @NonNull String dotFileName, @NonNull CharSequence content) {\n        PsiFile originFile = psiDirectory.findFile(dotFileName);\n        if (Objects.nonNull(originFile)) {\n            originFile.delete();\n        }\n        return createJavaFile(project, dotFileName, content);\n    }\n\n    /**\n     * Create file, throw exception when source file exists\n     *\n     * @param project\n     * @param dotFileName\n     * @param content\n     * @return\n     */\n    public static PsiJavaFile createJavaFile(@NonNull Project project, @NonNull String dotFileName, @NonNull CharSequence content) {\n        return (PsiJavaFile) PsiFileFactory.getInstance(project).createFileFromText(dotFileName, JavaFileType.INSTANCE, content);\n    }\n\n    /**\n     * Formatting code\n     *\n     * @param project\n     * @param psiElement File which needs to be formatted\n     */\n    public static void format(@NonNull Project project, @NonNull PsiElement psiElement) {\n        CodeStyleManager.getInstance(project).reformat(psiElement);\n    }\n\n    /**\n     * Find class\n     *\n     * @param className class name\n     * @return\n     */\n    public static Optional<PsiClass> findClass(@NonNull Project project, @NonNull String className) {\n        return findClass(project, className, psiClass -> true);\n    }\n\n    public static Optional<PsiClass> findClass(@NonNull Project project, @NonNull String className, Predicate<PsiClass> predicate) {\n        PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(project);\n\n        int idx = className.lastIndexOf(\".\");\n        if (-1 != idx) {\n            String packageName = className.substring(0, idx);\n            String name = className.substring(idx + 1);\n            PsiClass[] classes = shortNamesCache.getClassesByName(name, GlobalSearchScope.allScope(project));\n\n            if (0 != classes.length) {\n                for (PsiClass aClass : classes) {\n                    PsiJavaFile javaFile = (PsiJavaFile) aClass.getContainingFile();\n                    if (javaFile.getPackageName().equals(packageName) && predicate.test(aClass)) {\n                        return Optional.of(aClass);\n                    }\n                }\n            }\n        } else {\n            PsiClass[] classes = shortNamesCache.getClassesByName(className, GlobalSearchScope.allScope(project));\n            if (0 != classes.length) {\n                for (PsiClass aClass : classes) {\n                    if (predicate.test(aClass)) {\n                        return Optional.ofNullable(aClass);\n                    }\n                }\n            }\n        }\n\n        return Optional.empty();\n    }\n\n    /**\n     * Get or create a subdirectory\n     *\n     * @param project           current project\n     * @param subDirVirtualFile subdirectory file name\n     * @return\n     */\n    public static PsiDirectory getOrCreateSubDir(@NonNull Project project, @NonNull VirtualFile subDirVirtualFile) {\n        return PsiDirectoryFactory.getInstance(project).createDirectory(subDirVirtualFile);\n    }\n\n    /**\n     * Get or create a subdirectory\n     *\n     * @param currentProject        current project\n     * @param directoryAbsolutePath directoryRelativePath refer project's root path, see: Project.getBasePath()\n     * @return\n     */\n    public static PsiDirectory getOrCreateSubDirByPath(@NonNull Project currentProject, @NonNull String directoryAbsolutePath) {\n        String fileDirAbsolutePath = VerbalExpressionUtil.correctUrl(directoryAbsolutePath);\n        VirtualFile fileByIoFileDir = LocalFileSystem.getInstance().findFileByIoFile(new File(fileDirAbsolutePath));\n        if (Objects.isNull(fileByIoFileDir) || !fileByIoFileDir.exists()) {\n            return null;\n        }\n        PsiDirectory result = null;\n        try {\n            result = IdeaPlatformFileTreeUtil.getOrCreateSubDir(currentProject, fileByIoFileDir);\n        } catch (Throwable e) {\n            // this exception means the directory of directoryRelativePath does't exist! so just ignore it\n        }\n        return result;\n    }\n\n    /**\n     * Create child files\n     *\n     * @param currentVirtualFile\n     * @param subVirtualFileName\n     * @return\n     */\n    public static VirtualFile getOrCreateSubVirtualFile(@NonNull VirtualFile currentVirtualFile, @NonNull String subVirtualFileName) {\n        VirtualFile child = currentVirtualFile.findChild(subVirtualFileName);\n        if (Objects.isNull(child)) {\n            try {\n                child = currentVirtualFile.createChildDirectory(null, subVirtualFileName);\n            } catch (IOException e) {\n                // When the creation fails, the directory indicated by the currentVirtualFile root shall prevail\n                child = currentVirtualFile;\n            }\n        }\n        return child;\n    }\n\n    /**\n     * Create a sub file directory\n     *\n     * @param project\n     * @param currentVirtualFile\n     * @param subVirtualFileName\n     * @return\n     */\n    public static PsiDirectory getOrCreateSubDir(@NonNull Project project, @NonNull VirtualFile currentVirtualFile, @NonNull String subVirtualFileName) {\n        return getOrCreateSubDir(project, getOrCreateSubVirtualFile(currentVirtualFile, subVirtualFileName));\n    }\n\n    /**\n     * Create a sub file directory which class type is PsiDirectory\n     *\n     * @param currentPsiDir\n     * @param subDirName\n     * @return\n     */\n    public static PsiDirectory getOrCreateSubDir(@NonNull PsiDirectory currentPsiDir, @NonNull String subDirName) {\n        return Optional.ofNullable(currentPsiDir.findSubdirectory(subDirName)).orElseGet(() -> currentPsiDir.createSubdirectory(subDirName));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/JSONUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonParser;\nimport com.google.gson.JsonSyntaxException;\nimport lombok.NonNull;\n\n/**\n * JSON tool\n *\n * @author caofanCPU\n */\npublic class JSONUtil {\n\n    public static String formatStandardJSON(@NonNull String source) {\n        String result = source;\n        try {\n            Gson gson = new GsonBuilder().setPrettyPrinting().create();\n            JsonElement element = JsonParser.parseString(source);\n            result = gson.toJson(element);\n        } catch (JsonSyntaxException e) {\n            // Just ignore, and return the origin text\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/PropertiesUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport com.intellij.openapi.diagnostic.Logger;\nimport com.intellij.openapi.project.Project;\nimport com.xyz.caofancpu.d8ger.core.KeyEnum;\nimport com.xyz.caofancpu.d8ger.setting.D8gerProjectState;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.Properties;\n\n/**\n * Properties file tool\n *\n * @author caofanCPU\n */\npublic class PropertiesUtil {\n    private static final Logger LOG = Logger.getInstance(PropertiesUtil.class);\n\n    /**\n     * Load configuration file\n     *\n     * @return\n     */\n    public static Properties loadPropertiesFromRootResource(Project currentProject) {\n        Properties customerProperties = new Properties();\n        D8gerProjectState settings = D8gerProjectState.getInstance(currentProject);\n        customerProperties.setProperty(KeyEnum.MO.getKey(), settings.moCheck + ConstantUtil.ENGLISH_COMMA + settings.moPath);\n        customerProperties.setProperty(KeyEnum.MO_MAPPER.getKey(), settings.mapperCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperPath);\n        customerProperties.setProperty(KeyEnum.MO_EXAMPLE.getKey(), settings.mapperExampleCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperExamplePath);\n        customerProperties.setProperty(KeyEnum.MO_MAPPER_XML.getKey(), settings.mapperXmlCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperXmlPath);\n        customerProperties.setProperty(KeyEnum.MO_SQL.getKey(), settings.sqlCheck + ConstantUtil.ENGLISH_COMMA + settings.sqlPath);\n        customerProperties.setProperty(KeyEnum.SWAGGER_MO.getKey(), settings.voCheck + ConstantUtil.ENGLISH_COMMA + settings.voPath);\n        customerProperties.setProperty(KeyEnum.MO_HANDLER.getKey(), settings.handlerCheck + ConstantUtil.ENGLISH_COMMA + settings.handlerPath);\n        customerProperties.setProperty(KeyEnum.MO_CONTROLLER.getKey(), settings.controllerCheck + ConstantUtil.ENGLISH_COMMA + settings.controllerPath);\n        customerProperties.setProperty(KeyEnum.FORMAT_STYLE.getKey(), settings.formatStyleCheck + ConstantUtil.EMPTY);\n        customerProperties.setProperty(KeyEnum.SQL_DETECT_TIME_COLUMN.getKey(), settings.detectSQLTimeColumnCheck + ConstantUtil.EMPTY);\n        customerProperties.setProperty(KeyEnum.MO_MAPPER_ANNOTATION.getKey(), settings.mapperBetterThenRepositoryCheck + ConstantUtil.EMPTY);\n        customerProperties.setProperty(ConstantUtil.CONFIG_AUTHOR_KEY, settings.defaultAuthor);\n        customerProperties.setProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY, settings.defaultUrlPrefix);\n        customerProperties.setProperty(ConstantUtil.CONFIG_LANGUAGE_KEY, settings.defaultLocale);\n        return customerProperties;\n    }\n\n    /**\n     * Check if the configuration item is configured as 'true' or 'TRUE'\n     *\n     * @param properties\n     * @param propertyKey\n     * @return\n     */\n    public static boolean checkConfigTakeEffect(Properties properties, String propertyKey) {\n        String property = properties.getProperty(propertyKey);\n        if (StringUtils.isBlank(property)) {\n            // if no config, just ignore\n            return false;\n        }\n        String noWhiteCharProperty = VerbalExpressionUtil.cleanWhiteChar(property);\n        String[] itemConfigs = noWhiteCharProperty.split(ConstantUtil.ENGLISH_COMMA);\n        return Boolean.parseBoolean(itemConfigs[0]);\n    }\n\n    /**\n     * Detect if a configuration item contains a directory relative path,\n     * if true then return it, otherwise return null.\n     *\n     * @param properties\n     * @param propertyKey\n     * @return\n     */\n    public static String detectConfigDirectoryPath(Properties properties, String propertyKey) {\n        String property = properties.getProperty(propertyKey);\n        String noWhiteCharProperty = VerbalExpressionUtil.cleanWhiteChar(property);\n        String[] itemConfigs = noWhiteCharProperty.split(ConstantUtil.ENGLISH_COMMA);\n        if (itemConfigs.length == 1) {\n            // if there is just one item config, ignore too\n            return null;\n        }\n        // here, need to create file, so we should check need put it into custom directory or not\n        return StringUtils.isBlank(itemConfigs[1]) ? null : itemConfigs[1];\n    }\n\n    /**\n     * Check and detect if a configuration item contains a directory relative path,\n     * if true then return it, otherwise return null.\n     *\n     * @param properties\n     * @param propertyKey\n     * @return\n     */\n    public static String checkAndDetectConfigDirectoryPath(Properties properties, String propertyKey) {\n        if (!checkConfigTakeEffect(properties, propertyKey)) {\n            return null;\n        }\n        return detectConfigDirectoryPath(properties, propertyKey);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/StringAlignUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.JdbcUtils;\nimport lombok.Getter;\nimport lombok.NonNull;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.regex.Pattern;\n\n/**\n * Handle multi-lines align, batch add prefix | suffix\n *\n * @author caofanCPU\n */\n@Slf4j\npublic class StringAlignUtil {\n    /**\n     * White char regex\n     */\n    public static final Pattern WHITE_CHAR_PATTERN = Pattern.compile(\"(?:\\\\s)+\");\n\n    /**\n     * Compatibility separator pattern, support one or more lineBreak | English comma as ',' | Chinese comma as '，'\n     */\n    public static final Pattern ORIGIN_COMPATIBILITY_SEPARATOR = Pattern.compile(\"((?:\\\\n|(?:\\\\r\\\\n))|(?:,)|(?:，))+\");\n\n    /**\n     * Line begins with English comma\n     */\n    public static final Pattern START_WITH_ENGLISH_COMMA_PATTERN = Pattern.compile(\"^(?:,)+\");\n\n    /**\n     * Config key parser regex\n     */\n    public static final Pattern CONFIG_PARSER_PATTERN = Pattern.compile(\"(?:@<)(?:.*)(?:>@)\");\n\n    /**\n     * Format mysql\n     *\n     * @param sql\n     * @return\n     */\n    public static String formatMySQL(String sql) {\n        if (StringUtils.isBlank(sql)) {\n            return sql;\n        }\n        try {\n            String dbType = JdbcUtils.MYSQL;\n            List<SQLStatement> statementList = SQLUtils.toStatementList(sql, dbType);\n\n            StringBuilder out = new StringBuilder();\n            SQLASTOutputVisitor visitor = SQLUtils.createFormatOutputVisitor(out, statementList, dbType);\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            return out.toString().replaceAll(ConstantUtil.ORIGIN_TAB, ConstantUtil.TAB) + ConstantUtil.ENGLISH_SEMICOLON;\n        } catch (Throwable t) {\n            // any exception, give back the origin sql\n            return sql;\n        }\n    }\n\n    /**\n     * Handling multi lines by conventional separator\n     *\n     * @param originText\n     * @return\n     */\n    public static List<String> handleSplitMultiLines(@NonNull String originText) {\n        String legalText = originText.replaceAll(ORIGIN_COMPATIBILITY_SEPARATOR.pattern(), ConstantUtil.ENGLISH_COMMA)\n                .replaceAll(WHITE_CHAR_PATTERN.pattern(), ConstantUtil.EMPTY)\n                .replaceAll(START_WITH_ENGLISH_COMMA_PATTERN.pattern(), ConstantUtil.EMPTY);\n        String splitSymbol = ConstantUtil.ENGLISH_COMMA;\n        return CollectionUtil.splitDelimitedStringToList(legalText, splitSymbol, String::toString);\n    }\n\n    /**\n     * Format SQL columns, for example, add function or rename by using 'AS'\n     *\n     * @param originText\n     * @param formatAlignment\n     * @param prefix\n     * @param suffix\n     * @param formatSQL\n     * @param formatAsCamel\n     * @return\n     */\n    public static String formatSQLColumn(@NonNull String originText, Alignment formatAlignment, @NonNull String prefix, @NonNull String suffix, boolean formatSQL, boolean formatAsCamel) {\n        List<String> stringList = handleSplitMultiLines(originText);\n        List<String> completeFixList = CollectionUtil.transToList(stringList, item -> prefix + item + suffix);\n        int singleLineMaxChars = CollectionUtil.max(completeFixList, String::length).intValue();\n        if (Objects.isNull(formatAlignment)) {\n            formatAlignment = Alignment.LEFT;\n        }\n        List<String> formattedLineList = formatSQLColumn(singleLineMaxChars, formatAlignment, completeFixList);\n        if (formatSQL && formatAsCamel) {\n            stringList = CollectionUtil.transToList(stringList, StringAlignUtil::cleanUnderLineForSQLAliasName);\n        }\n        Map<Integer, String> indexMap = CollectionUtil.transToMap(stringList, stringList::indexOf, Function.identity());\n        StringBuilder result = new StringBuilder();\n        for (int i = 0; i < formattedLineList.size(); i++) {\n            String column = indexMap.get(i);\n            result.append(formattedLineList.get(i));\n            if (formatSQL) {\n                result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(\"AS\").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(column);\n            }\n            result.append(ConstantUtil.ENGLISH_COMMA).append(ConstantUtil.NEXT_LINE);\n        }\n        return StringUtils.isEmpty(result) ? result.toString() : result.deleteCharAt(result.lastIndexOf(ConstantUtil.ENGLISH_COMMA)).toString();\n    }\n\n    /**\n     * format multi-lines and handling encryption | decryption\n     *\n     * @param originText\n     * @param alignStyle\n     * @param algorithm\n     * @param endOperate\n     * @return\n     */\n    public static String formatEND(@NonNull String originText, Alignment alignStyle, Algorithm algorithm, ENDOperate endOperate) {\n        List<String> originStringList = handleSplitMultiLines(originText);\n        // init param\n        if (Objects.isNull(alignStyle)) {\n            alignStyle = Alignment.LEFT;\n        }\n        if (Objects.isNull(algorithm)) {\n            algorithm = Algorithm.AES;\n        }\n        if (Objects.isNull(endOperate)) {\n            endOperate = ENDOperate.ENCRYPTION_AND_DECRYPTION;\n        }\n\n        // calculate operate\n        List<ENDOperate> operateList = new ArrayList<>(4);\n        if (ENDOperate.ENCRYPTION_AND_DECRYPTION == endOperate) {\n            operateList.add(ENDOperate.ENCRYPTION);\n            operateList.add(ENDOperate.DECRYPTION);\n            if (Algorithm.PINYIN == algorithm) {\n                operateList.add(ENDOperate.PINYIN);\n            }\n        } else {\n            operateList.add(endOperate);\n            if (ENDOperate.ENCRYPTION == endOperate && Algorithm.PINYIN == algorithm) {\n                operateList.add(ENDOperate.PINYIN);\n            }\n        }\n\n        Map<ENDOperate, List<String>> handleResultMap = new HashMap<>(8, 0.75f);\n        handleResultMap.put(ENDOperate.ORIGIN, originStringList);\n        if (operateList.contains(ENDOperate.PINYIN)) {\n            // calculate pinyin\n            handleResultMap.put(ENDOperate.PINYIN, CollectionUtil.transToList(originStringList, String::toString));\n        }\n        if (operateList.contains(ENDOperate.ENCRYPTION)) {\n            List<String> targetList;\n\n            if (operateList.contains(ENDOperate.PINYIN)) {\n                targetList = handleResultMap.get(ENDOperate.PINYIN);\n            } else {\n                targetList = originStringList;\n            }\n            if (Algorithm.PINYIN == algorithm) {\n                // PINYIN encryption TODO\n                handleResultMap.put(ENDOperate.ENCRYPTION, CollectionUtil.transToList(targetList, String::toUpperCase));\n            } else {\n                // AES encryption TODO\n                handleResultMap.put(ENDOperate.ENCRYPTION, CollectionUtil.transToList(targetList, String::toLowerCase));\n            }\n        }\n        if (operateList.contains(ENDOperate.DECRYPTION)) {\n            List<String> targetList;\n            if (operateList.contains(ENDOperate.ENCRYPTION)) {\n                targetList = handleResultMap.get(ENDOperate.ENCRYPTION);\n            } else {\n                targetList = originStringList;\n            }\n            if (Algorithm.PINYIN == algorithm) {\n                // PINYIN decryption TODO\n                handleResultMap.put(ENDOperate.DECRYPTION, CollectionUtil.transToList(targetList, String::toLowerCase));\n            } else {\n                // AES decryption TODO\n                handleResultMap.put(ENDOperate.DECRYPTION, CollectionUtil.transToList(targetList, String::toUpperCase));\n            }\n        }\n\n        // align string\n        for (ENDOperate key : handleResultMap.keySet()) {\n            List<String> itemList = handleResultMap.get(key);\n            int maxCharLength = CollectionUtil.max(itemList, String::length).intValue();\n            handleResultMap.put(key, formatSQLColumn(maxCharLength, alignStyle, itemList));\n        }\n\n        StringBuilder result = new StringBuilder();\n        List<String> formattedOriginList = handleResultMap.get(ENDOperate.ORIGIN);\n        List<String> pinyinList = handleResultMap.get(ENDOperate.PINYIN);\n        List<String> encryptionList = handleResultMap.get(ENDOperate.ENCRYPTION);\n        List<String> decryptionList = handleResultMap.get(ENDOperate.DECRYPTION);\n        for (int i = 0; i < formattedOriginList.size(); i++) {\n            result.append(formattedOriginList.get(i));\n            if (i != formattedOriginList.size() - 1) {\n                result.append(ConstantUtil.ENGLISH_COMMA);\n            } else {\n                result.append(ConstantUtil.SPACE);\n            }\n            if (CollectionUtil.isNotEmpty(pinyinList)) {\n                result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(\"-->(PinYin Result)\").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(pinyinList.get(i));\n                if (i != formattedOriginList.size() - 1) {\n                    result.append(ConstantUtil.ENGLISH_COMMA);\n                } else {\n                    result.append(ConstantUtil.SPACE);\n                }\n            }\n            if (CollectionUtil.isNotEmpty(encryptionList)) {\n                result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(\"-->(Encryption Result)\").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(encryptionList.get(i));\n                if (i != formattedOriginList.size() - 1) {\n                    result.append(ConstantUtil.ENGLISH_COMMA);\n                } else {\n                    result.append(ConstantUtil.SPACE);\n                }\n            }\n            if (CollectionUtil.isNotEmpty(decryptionList)) {\n                result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(\"-->(Decryption Result)\").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(decryptionList.get(i));\n                if (i != formattedOriginList.size() - 1) {\n                    result.append(ConstantUtil.ENGLISH_COMMA);\n                } else {\n                    result.append(ConstantUtil.SPACE);\n                }\n            }\n            result.append(ConstantUtil.NEXT_LINE);\n        }\n\n        return result.toString();\n    }\n\n    public static String cleanUnderLineForSQLAliasName(@NonNull String columnName) {\n        String result = columnName;\n        for (int i = 0; i < 4; i++) {\n            if (VerbalExpressionUtil.CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE.matcher(result).matches()) {\n                break;\n            }\n            result = VerbalExpressionUtil.camelUnderLineNameConverter(result);\n        }\n        return result;\n    }\n\n    /**\n     * Format by splitSymbol, such as ',' or NEXT_LINE\n     *\n     * @param originText\n     * @param splitSymbol\n     * @param currentAlignment\n     * @return\n     */\n    public static String formatBySplitSymbol(String originText, String splitSymbol, Alignment currentAlignment) {\n        List<String> stringList = CollectionUtil.splitDelimitedStringToList(originText, splitSymbol, String::toString);\n        return formatMultiLine(stringList, currentAlignment);\n    }\n\n    /**\n     * MultiLine format\n     *\n     * @param stringList\n     * @param currentAlignment\n     * @return\n     */\n    public static String formatMultiLine(List<String> stringList, Alignment currentAlignment) {\n        int singleLineMaxChars = CollectionUtil.max(stringList, String::length).intValue();\n        return format(singleLineMaxChars, currentAlignment, stringList);\n    }\n\n    /**\n     * Format multi-string\n     *\n     * @param singleLineMaxChars\n     * @param currentAlignment\n     * @param stringList\n     * @return\n     */\n    public static String format(int singleLineMaxChars, Alignment currentAlignment, List<String> stringList) {\n        checkAlignmentParam(singleLineMaxChars, currentAlignment);\n        StringBuilder result = new StringBuilder();\n        for (String wanted : stringList) {\n            switch (currentAlignment) {\n                case RIGHT:\n                    pad(result, singleLineMaxChars - wanted.length());\n                    result.append(wanted);\n                    break;\n                case CENTER:\n                    int toAdd = singleLineMaxChars - wanted.length();\n                    pad(result, toAdd / 2);\n                    result.append(wanted);\n                    pad(result, toAdd - toAdd / 2);\n                    break;\n                case LEFT:\n                    result.append(wanted);\n                    pad(result, singleLineMaxChars - wanted.length());\n                    break;\n            }\n            result.append(ConstantUtil.NEXT_LINE);\n        }\n        return result.toString();\n    }\n\n    /**\n     * Format sql columns, return multi-lines\n     *\n     * @param stringList\n     * @param singleLineMaxChars\n     * @param currentAlignment\n     * @return\n     */\n    public static List<String> formatSQLColumn(int singleLineMaxChars, Alignment currentAlignment, List<String> stringList) {\n        String result = format(singleLineMaxChars, currentAlignment, stringList);\n        return CollectionUtil.splitDelimitedStringToList(result, ConstantUtil.NEXT_LINE, String::toString);\n    }\n\n    /**\n     * Supplementary space\n     *\n     * @param to\n     * @param howMany\n     */\n    public static void pad(StringBuilder to, int howMany) {\n        for (int i = 0; i < howMany; i++) {\n            to.append(ConstantUtil.SPACE);\n        }\n    }\n\n    /**\n     * Split text, especially is paragraph\n     *\n     * @param text\n     * @param singleLineMaxChars\n     * @return\n     */\n    public static List<String> splitInputText(String text, int singleLineMaxChars) {\n        List<String> list = new ArrayList<>();\n        if (StringUtils.isBlank(text)) {\n            return list;\n        }\n        if (singleLineMaxChars < 0) {\n            throw new IllegalArgumentException(\"singleLineMaxChars must be positive.\");\n        }\n        for (int i = 0; i < text.length(); i = i + singleLineMaxChars) {\n            list.add(text.substring(i, Math.min(i + singleLineMaxChars, text.length())));\n        }\n        return list;\n    }\n\n    /**\n     * Basic check\n     *\n     * @param singleLineMaxChars\n     * @param align\n     */\n    public static void checkAlignmentParam(int singleLineMaxChars, Alignment align) {\n        if (singleLineMaxChars < 0) {\n            throw new IllegalArgumentException(\"singleLineMaxChars must be positive.\");\n        }\n        if (align != Alignment.LEFT && align != Alignment.CENTER && align != Alignment.RIGHT) {\n            throw new IllegalArgumentException(\"invalid justification arg.\");\n        }\n    }\n\n    /**\n     * Format paragraph\n     *\n     * @param text\n     * @param singleLineMaxChars\n     * @param currentAlignment\n     * @return\n     */\n    public String formatText(String text, int singleLineMaxChars, Alignment currentAlignment) {\n        List<String> stringList = splitInputText(text, singleLineMaxChars);\n        return format(singleLineMaxChars, currentAlignment, stringList);\n    }\n\n    public enum Alignment {\n        LEFT,\n        CENTER,\n        RIGHT,\n        ;\n    }\n\n    public enum Algorithm {\n        AES(\"1\"),\n        PINYIN(\"2\");\n        @Getter\n        private String value;\n\n        Algorithm(String value) {\n            this.value = value;\n        }\n    }\n\n    public enum ENDOperate {\n        /**\n         * Fast sqrt magic number in 64 bit.\n         */\n        ORIGIN(\"0x5fe6ec85e7de30da\"),\n        /**\n         * Fast sqrt magic number, haha, can you guess it?\n         */\n        PINYIN(\"0x5f3759df\"),\n        ENCRYPTION_AND_DECRYPTION(\"0\"),\n        ENCRYPTION(\"1\"),\n        DECRYPTION(\"2\"),\n\n        ;\n        @Getter\n        private String value;\n\n        ENDOperate(String value) {\n            this.value = value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/xyz/caofancpu/d8ger/util/VerbalExpressionUtil.java",
    "content": "package com.xyz.caofancpu.d8ger.util;\n\nimport lombok.NonNull;\nimport org.apache.commons.lang3.StringUtils;\nimport ru.lanwen.verbalregex.VerbalExpression;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * Regex common util\n * Tips: https://github.com/VerbalExpressions/JavaVerbalExpressions\n * 1. DO NOT USE or(), take oneOf() | add(Regex string) place of it\n * 2. USE multi segment capt()+endCapt() for easy reading\n * 3. add() is very powerful, some times it's easy to express OR logic\n *\n * @author caofanCPU\n */\npublic class VerbalExpressionUtil {\n    /**\n     * Judge current system is WINDOWS, by the way, WINDOWS is real ***...\n     */\n    public static final boolean CURRENT_OS_IS_WINDOWS = Objects.equals(System.getProperty(\"os.name\").toLowerCase(), \"windows\");\n\n    /**\n     * Uppercase regular expression\n     */\n    public static final Pattern HUMP_TO_UNDERLINE = Pattern.compile(\"[A-Z]\");\n\n    /**\n     * No '_' or '-' and begin with [A-Z] regex, it will trigger to execute CamelToUnderline when regex detect is true\n     */\n    public static final Pattern CAMEL_UNDERLINE_1_NO_UNDERLINE_CAPITALIZE = Pattern.compile(\"^(?![_-])(?:[A-Z])[a-zA-Z0-9\\\\W]+$\");\n\n    /**\n     * No '_' or '-' and begin with [a-z] regex, it will trigger to execute CamelToUnderline when regex detect is true\n     */\n    public static final Pattern CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE = Pattern.compile(\"^(?![_-])(?:[a-z])[a-zA-Z0-9\\\\W]+$\");\n\n    /**\n     * No upper case regex, it will trigger to execute LowerCaseToUpperCase when regex detect is true\n     */\n    public static final Pattern CAMEL_UNDERLINE_3_NO_UPPER_CASE = Pattern.compile(\"^(?![A-Z])[a-z0-9\\\\W_-]+$\");\n\n    /**\n     * No lower case, it will trigger to execute UpperCaseToCamel when regex detect is true\n     */\n    public static final Pattern CAMEL_UNDERLINE_4_NO_LOWER_CASE = Pattern.compile(\"^(?![a-z])[A-Z0-9\\\\W_-]+$\");\n\n    /**\n     * Swagger field | interface position order regular match expression\n     */\n    public static final Pattern SWAGGER_MODEL_PATTERN = Pattern.compile(\"(((?:position)|(?:order))(?:\\\\s)*(?:=)(?:\\\\s)*(?:\\\\d)*)\");\n\n    /**\n     * When we clear white chars, considering spaces can be part of data we should except spaces in JSON string\n     */\n    public static final Pattern WHITE_CHAR_IN_JSON_REGEX_0 = Pattern.compile(\"(?:[\\\\t\\\\n\\\\x0B\\\\f\\\\r])+\");\n\n    /**\n     * Beauty JSON view regex\n     */\n    public static final Pattern WHITE_CHAR_IN_JSON_REGEX_1 = Pattern.compile(\"(?:\\\")+[ ]*[:：]+[ ]*\");\n\n    /**\n     * JSON string definition regex\n     */\n    public static final Pattern JSON_STRING_JUDGE_REGEX = Pattern.compile(\"^(?:\\\\{).*(?:})$\");\n\n    /**\n     * Next line separator regex\n     */\n    public static final Pattern NEXT_LINE_REGEX = Pattern.compile(\"(?:\\\\n|(?:\\\\r\\\\n))+\");\n\n    /**\n     * English dot as key symbol regex\n     */\n    public static final Pattern KEY_ENGLISH_DOT_REGEX = Pattern.compile(\"\\\\.\");\n\n    /**\n     * Symbols '[', ']', '<', '>' OR relationship regex\n     */\n    public static final Pattern KEY_COLLECTION_EDGE_SYMBOL_REGEX = Pattern.compile(\"[\\\\[\\\\]<>]\");\n\n    /**\n     * String.replaceAll(), matched result can be access by $0\n     */\n    public static final String REPLACE_MATCH_RESULT_SYMBOL = \"$0\";\n\n    /**\n     * Java file as source code, which prefix path\n     */\n    public static Pattern PREFIX_JAVA_SOURCE_FILE_PATH = Pattern.compile(\"^(?:.*)(?:[/\\\\\\\\]*)(?:src)(?:[/\\\\\\\\]+)(?:main)(?:[/\\\\\\\\]+)(?:java)(?:[/\\\\\\\\]+)\");\n\n    /**\n     * File path split symbol\n     */\n    public static Pattern FILE_PATH_SPLIT_SYMBOL = Pattern.compile(\"(?:[/\\\\\\\\]+)\");\n\n    /**\n     * File path prefix split in Windows OS\n     */\n    public static Pattern WINDOWS_PREFIX_JAVA_SOURCE_FILE_PATH = Pattern.compile(\"(?:[a-zA-Z]*:\\\\.*)\");\n\n    /**\n     * CaoFAn -->(Uncapitalize) caoFAn -->(CamelToUnderline) cao_f_an -->(LowerCaseToUpperCase) CAO_F_AN -->(UpperCaseToCamel) CaoFAn\n     *\n     * @param originName\n     * @return\n     */\n    public static String camelUnderLineNameConverter(@NonNull String originName) {\n        int matchNo = 0;\n        if (CAMEL_UNDERLINE_1_NO_UNDERLINE_CAPITALIZE.matcher(originName).matches()) {\n            matchNo = 1;\n        }\n        if (CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE.matcher(originName).matches()) {\n            matchNo = 2;\n        }\n        if (CAMEL_UNDERLINE_3_NO_UPPER_CASE.matcher(originName).matches()) {\n            matchNo = 3;\n        }\n        if (CAMEL_UNDERLINE_4_NO_LOWER_CASE.matcher(originName).matches()) {\n            matchNo = 4;\n        }\n        if (matchNo == 0) {\n            return originName;\n        }\n        String result = originName;\n        switch (matchNo) {\n            case 1:\n                // Uncapitalize\n                result = StringUtils.uncapitalize(originName);\n                break;\n            case 2:\n                // CamelToUnderline\n                result = StringUtils.lowerCase(originName.replaceAll(HUMP_TO_UNDERLINE.pattern(), \"_$0\"));\n                break;\n            case 3:\n                // LowerCaseToUpperCase\n                result = StringUtils.upperCase(originName);\n                break;\n            case 4:\n                // UpperCaseToCamel\n                String[] words = originName.split(\"[_-]\");\n                List<String> resultItemWordList = new ArrayList<>(words.length);\n                for (String word : words) {\n                    resultItemWordList.add(StringUtils.capitalize(StringUtils.lowerCase(word)));\n                }\n                result = CollectionUtil.join(resultItemWordList, ConstantUtil.EMPTY);\n                break;\n            default:\n                break;\n        }\n        return result;\n    }\n\n    /**\n     * Swagger field | interface position order regular replacement\n     *\n     * @param originString\n     * @param replaceString\n     * @return\n     */\n    public static String regexHandleSwaggerModelProperty(String originString, final String replaceString) {\n        Matcher matcher = SWAGGER_MODEL_PATTERN.matcher(originString);\n        return matcher.replaceAll(replaceString);\n    }\n\n    /**\n     * Extract matched content list by pattern\n     *\n     * @param originContext\n     * @param pattern\n     * @return\n     */\n    public static List<String> extractMatchContent(@NonNull String originContext, Pattern pattern) {\n        List<String> resultList = new ArrayList<>();\n        Matcher matcher = pattern.matcher(originContext);\n        while (matcher.find()) {\n            // add current matched group value\n            resultList.add(matcher.group());\n        }\n        return resultList;\n    }\n\n    /**\n     * Create a regular expression object\n     *\n     * @param matchKeyWord\n     * @return\n     */\n    public static VerbalExpression buildRegex(String matchKeyWord) {\n        return VerbalExpression.regex().capt().find(matchKeyWord).endCapt().build();\n    }\n\n    /**\n     * Disjunction regular expression\n     *\n     * @param originComment\n     * @return\n     */\n    public static String extractComment(String originComment) {\n        VerbalExpression regex = VerbalExpression.regex()\n                .capt()\n                .oneOf(\"/\", \"\\\\*\", ConstantUtil.NEXT_LINE, ConstantUtil.TAB, ConstantUtil.ORIGIN_TAB, ConstantUtil.MINI_TAB).oneOrMore()\n                .endCapt()\n                .build();\n        return executePatternRex(regex, originComment, ConstantUtil.EMPTY);\n    }\n\n    /**\n     * Regular replacement\n     *\n     * @param regexExpression\n     * @param originText\n     * @param replacer\n     * @return\n     */\n    public static String executePatternRex(VerbalExpression regexExpression, String originText, String replacer) {\n        Pattern pattern = Pattern.compile(regexExpression.toString());\n        Matcher matcher = pattern.matcher(originText);\n        return matcher.replaceAll(replacer);\n    }\n\n    /**\n     * Regular replacement of relatively large strings, using StringBuilder to store strings\n     *\n     * @param regexExpression\n     * @param originText\n     * @param replacer\n     * @return\n     */\n    public static StringBuilder executePatternRex(VerbalExpression regexExpression, StringBuilder originText, StringBuilder replacer) {\n        Pattern pattern = Pattern.compile(regexExpression.toString());\n        Matcher matcher = pattern.matcher(originText);\n        return new StringBuilder(matcher.replaceAll(replacer.toString()));\n    }\n\n    /**\n     * Camel convert to underline\n     *\n     * @param originName\n     * @return\n     */\n    public static String sqlUnderLineName(String originName) {\n        return StringUtils.lowerCase(StringUtils.uncapitalize(originName).replaceAll(HUMP_TO_UNDERLINE.pattern(), \"_$0\"));\n    }\n\n    /**\n     * Remove the trailing one or more 'Mo's from the original Model object's name\n     *\n     * @param originMoName\n     * @return\n     */\n    public static String cropMoSuffix(@NonNull String originMoName) {\n        VerbalExpression regex = VerbalExpression.regex().capt().find(ConstantUtil.MO_SUFFIX).oneOrMore().endCapt().endOfLine().build();\n        return executePatternRex(regex, originMoName, ConstantUtil.EMPTY);\n    }\n\n    /**\n     * url path correction, remove rare '/' to keep just one '/' and begin with it\n     * compatible windows file path\n     *\n     * @param property\n     * @return\n     */\n    public static String correctUrl(String property) {\n        String resultPrefix = File.separator;\n        try {\n            if (CURRENT_OS_IS_WINDOWS) {\n                String[] splits = property.split(ConstantUtil.ENGLISH_COLON);\n                resultPrefix = splits[0] + ConstantUtil.ENGLISH_COLON;\n                if (splits.length == 1 || StringUtils.isBlank(splits[1])) {\n                    return resultPrefix + \"/\";\n                }\n                property = splits[1];\n            } else {\n                property = resultPrefix + property;\n            }\n        } catch (Throwable e) {\n            throw new RuntimeException(\"Illegal file path, please check carefully!\");\n        }\n        VerbalExpression regex = VerbalExpression.regex()\n                .capt()\n                .oneOf(\"/\", \"\\\\\\\\\").oneOrMore()\n                .endCapt()\n                .build();\n        String tempResult = executePatternRex(regex, property, \"/\");\n        return CURRENT_OS_IS_WINDOWS ? resultPrefix + tempResult : tempResult;\n    }\n\n    /**\n     * Convert path string to package,\n     * for example: /ModuleName//src/main/java/com/xyz/caofancpu/d8ger/test --> com.xyz.caofancpu.d8ger.test\n     * Compatible with WINDOWS: D:/ModuleName//src\\main\\\\java/com/xyz/caofancpu/d8ger/test --> com.xyz.caofancpu.d8ger.test\n     *\n     * @param originPath\n     * @return\n     */\n    public static String convertPathToPackage(String originPath) {\n        String first = originPath.replaceAll(PREFIX_JAVA_SOURCE_FILE_PATH.pattern(), ConstantUtil.EMPTY);\n        String second = first.replaceAll(FILE_PATH_SPLIT_SYMBOL.pattern(), ConstantUtil.ENGLISH_FULL_STOP);\n        if (StringUtils.isBlank(second) || second.length() < 2) {\n            throw new RuntimeException(\"Illegal file path, please check carefully!\");\n        }\n        if (CURRENT_OS_IS_WINDOWS) {\n            String winR = second.replaceAll(WINDOWS_PREFIX_JAVA_SOURCE_FILE_PATH.pattern(), ConstantUtil.EMPTY);\n            if (StringUtils.isBlank(winR)) {\n                throw new RuntimeException(\"Illegal file path, please check carefully!\");\n            }\n            return winR;\n        }\n        return Objects.equals(second.charAt(0), '.') ? second.substring(1) : second;\n    }\n\n    public static String convertPathToPackage2(String originPath) {\n        VerbalExpression regex1 = VerbalExpression.regex()\n                .startOfLine().anything()\n                .capt().oneOf(\"/\", \"\\\\\\\\\").zeroOrMore().endCapt()\n                .capt().find(\"src\").oneOf(\"/\", \"\\\\\\\\\").oneOrMore().endCapt()\n                .capt().find(\"main\").oneOf(\"/\", \"\\\\\\\\\").oneOrMore().endCapt()\n                .capt().find(\"java\").oneOf(\"/\", \"\\\\\\\\\").oneOrMore().endCapt()\n                .build();\n        String first = executePatternRex(regex1, originPath, ConstantUtil.EMPTY);\n        VerbalExpression regex2 = VerbalExpression.regex()\n                .capt()\n                .oneOf(\"/\", \"\\\\\\\\\").oneOrMore()\n                .endCapt()\n                .build();\n        String second = executePatternRex(regex2, first, ConstantUtil.ENGLISH_FULL_STOP);\n        if (StringUtils.isBlank(second) || second.length() < 2) {\n            throw new RuntimeException(\"Illegal file path, please check carefully!\");\n        }\n        if (CURRENT_OS_IS_WINDOWS) {\n            VerbalExpression regex3 = VerbalExpression.regex()\n                    .capt()\n                    .add(\"[a-zA-Z]\").zeroOrMore().then(\":\").then(\".\").zeroOrMore()\n                    .endCapt()\n                    .build();\n            String winR = executePatternRex(regex3, second, ConstantUtil.EMPTY);\n            if (StringUtils.isBlank(winR)) {\n                throw new RuntimeException(\"Illegal file path, please check carefully!\");\n            }\n            return winR;\n        }\n        return Objects.equals(second.charAt(0), '.') ? second.substring(1) : second;\n    }\n\n\n    /**\n     * Beautify multiple newlines\n     * (?:\\\\n|(?:\\\\r\\\\n))+\n     *\n     * @param source\n     * @return\n     */\n    public static String beautyNextLine(@NonNull String source) {\n        VerbalExpression regex = VerbalExpression.regex()\n                .lineBreak().oneOrMore()\n                .build();\n        return executePatternRex(regex, source, ConstantUtil.NEXT_LINE);\n    }\n\n    /**\n     * Clear whitespace\n     * (?:\\\\s)+\n     *\n     * @param source\n     * @return\n     */\n    public static String cleanWhiteChar(@NonNull String source) {\n        VerbalExpression regex = VerbalExpression.regex()\n                .space().oneOrMore()\n                .build();\n        return executePatternRex(regex, source, ConstantUtil.EMPTY);\n    }\n\n\n    /**\n     * Clear whitespace in JSON string\n     *\n     * @param source\n     * @return\n     */\n    public static String cleanJSONWhiteChar(@NonNull String source) {\n        return source.replaceAll(WHITE_CHAR_IN_JSON_REGEX_0.pattern(), ConstantUtil.EMPTY)\n                .replaceAll(WHITE_CHAR_IN_JSON_REGEX_1.pattern(), ConstantUtil.ENGLISH_DOUBLE_QUOTES + ConstantUtil.ENGLISH_COLON);\n    }\n}\n"
  },
  {
    "path": "src/main/resources/META-INF/plugin.xml",
    "content": "<idea-plugin>\n    <id>com.xyz.caofancpu.D8gerAutoCode</id>\n    <name>D8gerAutoCode</name>\n    <vendor email=\"xyb5to0ZCY@gmail.com\" url=\"http://www.debuggerpowerzcy.top/about/\">D8ger•帝八哥</vendor>\n\n    <description>\n        <![CDATA[Java Automatic coding and Multi-lines wrapping and Linux commands and Regex skill are integrated by one plugin.\n        <p>\n        As JetBrains' said, I believe that you should be good use of tools will save you precious hours on your busing work.<br>\n        I always wonder, \"If someone else has already solved the repeating work, why do I need to repeat it again?\"<br>\n        Well, that's a valid question for my drive to find the repeat parts at daily work and develop this plugin to save my time.<br>\n        After 13 version iterations, I believe you're really worthy of using this plugin.<br>\n        重复编码老瞎忙,️ 写来写去那几行. 不知工具在何方? 八哥智能一键帮!<br>\n        Java自动代码生成利器, 配合<a href=\"https://github.com/caofanCPU/LaoYouTiao\">LaoYouTiao</a>, 还有强大的字符串批处理, Linux命令工具, 正则表达式奇淫巧技. <br>\n        <ul>\n            <li><a href=\"https://github.com/caofanCPU/D8gerAutoCode\">项目|Project</a><br></li>\n            <li><a href=\"http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\">博客指南|Blog guide</a><br></li>\n            <li><a href=\"http://file.debuggerpowerzcy.top/power/DYOU.mp4\">视频教程</a>||||||\n                <a href=\"https://www.youtube.com/watch?v=LZfC2_u-8aE\">Video Manual</a><br>\n            </li>\n            <li><a href=\"https://github.com/caofanCPU/D8gerAutoCode/blob/master/README_CN.md\">新手教程</a>||||||\n                <a href=\"https://github.com/caofanCPU/D8gerAutoCode/blob/master/README.md\">Tutorial</a><br>\n            </li>\n        </ul>\n        </p>\n        <img src=\"https://raw.githubusercontent.com/caofanCPU/D8gerAutoCode/master/src/main/resources/icons/DSP-V5.jpeg\" /><br>\n        ]]>\n    </description>\n\n    <!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html\n         on how to target different products -->\n    <!-- uncomment to enable plugin in all products\n    :<depends>com.intellij.modules.lang</depends>\n    -->\n\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <!-- Add your extensions here -->\n        <applicationService serviceImplementation=\"com.xyz.caofancpu.d8ger.setting.D8gerApplicationState\"/>\n        <postStartupActivity implementation=\"com.xyz.caofancpu.d8ger.activity.D8gerActivity\"/>\n\n        <projectService serviceImplementation=\"com.xyz.caofancpu.d8ger.setting.D8gerProjectState\"/>\n        <projectConfigurable parentId=\"default\" instance=\"com.xyz.caofancpu.d8ger.setting.D8gerSettingsConfigurable\"\n                             id=\"com.xyz.caofancpu.d8ger.setting.D8gerSettingsConfigurable\"\n                             displayName=\"D8gerAutoCode\"\n                             nonDefaultProject=\"false\"/>\n    </extensions>\n\n    <actions>\n        <!-- refer https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=991968\n                download 16.png as icon, 32.svg as plugin logo-->\n        <!-- Add your customer group here -->\n        <group id=\"D8ger\" text=\"D8ger\" description=\"D8gerAutoCode\" popup=\"true\" icon=\"/icons/D8Main.png\">\n            <add-to-group group-id=\"ToolsMenu\" anchor=\"last\"/>\n            <separator/>\n\n            <!-- Add your actions here -->\n            <action id=\"D8gerAutoCode\" class=\"com.xyz.caofancpu.d8ger.action.D8gerAutoCodeAction\" text=\"D8gerAutoCode\" description=\"D8gerAutoCode\" icon=\"/icons/D8Oxygen.png\">\n                <keyboard-shortcut keymap=\"$default\" first-keystroke=\"alt shift ctrl D\"/>\n            </action>\n\n            <action id=\"SwaggerModelAutoRender\" class=\"com.xyz.caofancpu.d8ger.action.SwaggerModelAutoRenderAction\" text=\"SwaggerModelAutoRender\" description=\"SwaggerModelAutoRender\" icon=\"/icons/Ocket.png\">\n                <keyboard-shortcut keymap=\"$default\" first-keystroke=\"alt shift ctrl O\"/>\n            </action>\n        </group>\n    </actions>\n\n    <idea-version since-build=\"193\"/>\n\n    <depends>com.intellij.modules.platform</depends>\n\n    <depends>com.intellij.modules.java</depends>\n\n    <depends>com.intellij.java</depends>\n\n    <change-notes>\n        <![CDATA[\n        <li>If you like D8gerAutoCode, please star <a href=\"https://github.com/caofanCPU/D8gerAutoCode\">the source project</a> for supporting me, thanks!</li>\n        <li><h1>4.1</h1></li>\n        <ul>\n        <li>BugFix:<br>\n            <ul>\n            <li>Fix 'D8gerAutoCode' error file path parsing while in WINDOWS system. For more detail, please refer <a href=\"https://github.com/caofanCPU/D8gerAutoCode/issues/2\">issue2</a></li>\n            </ul>\n        </li>\n        </ul>\n        </br>\n        <li><h1>4.0(HIGH.START)</h1></li>\n        <ul>\n        <li>Important note: This time the function is migrated and upgraded, the plug-in has been divided into functions, the purpose is to be full-time and dedicated, and the general functions are sinking to serve more programmers<br>\n            <ul>\n                <li>No.0: Each plug-in is positioned in two aspects, one is efficient coding, and the other is high-quality knowledge links to help users obtain enough useful information to improve their skills</li>\n                <li>No.1: <a href=\"https://github.com/caofanCPU/LaoYouTiao\">LaoYouTiao</a>, Published, located JetBrains full product plug-in, general functions, covering text parsing, numerical processing, shell script processing</li>\n                <li>No.2: <a href=\"https://github.com/caofanCPU/D8gerAutoCode\">D8gerAutoCode</a>, Published, located IntelliJ IDEA, auto coding</li>\n                <li>No.3: D8gerByteSleep, Hatching, located PyCharm</li>\n                <li>No.4: D8gerJustGo, Hatching, located GoLand</li>\n                <li>No.5: D8gerAndison, Hatching, located Android Studio</li>\n                <li>No.6: D8gerWebit, Hatching, located WebStorm</li>\n                <li>No.7: RoadMap refers <a href=\"https://www.processon.com/view/5f96a5f35653bb06ef1870e8\">DSP(D8ger Series Plan)</a></li>\n            </ul>\n        </li>\n        <li>Function migration:<br>\n            <ul>\n            <li>BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore are migrated into plugin named <a href=\"https://github.com/caofanCPU/LaoYouTiao\">LaoYouTiao</a>.</li>\n            <li>The shortcut keys and usage methods have not changed, only the code generation functions related to Java are retained.</li>\n            </ul>\n        </li>\n        </ul>\n        </br>\n        <li><h1>3.2</h1></li>\n        <ul>\n        <li>BugFix:<br>\n            <ul>\n            <li>Fix 'BeautifulJSON' issue when parsing complex JSON string.</li>\n            </ul>\n        </li>\n        <li>Optimization: 'CamelUnderlineConvert' now supports timestamp-dateTime convert, select the text and use shortcut `alt` + `shift` + `cmd` + `U` to find out.<br> </li>\n        </ul>\n        </br>\n        <li><h1>3.4</h1></li>\n        <ul>\n        <li>Addition: 'OhMyZSH' easter eggs, try to type 'ohmyzsh' in the blank file in IDEA to get some useful linux commands. I'm sure you'll save much time.<br> </li>\n        <li>BugFix: Fix donate url(I'm waiting for your 🌟 the project on the github).<br> </li>\n        <li>Optimization: 'BeautifulJSON', 'SimplifyOneLine' and 'BeautifulMySQL' now supports section or whole document convert.<br> </li>\n        </ul>\n        </br>\n        <li><h1>3.2</h1></li>\n        <ul>\n        <li>BugFix:<br>\n            <ul>\n            <li>Fix 'BeautifulJSON' issue when parsing complex JSON string.</li>\n            </ul>\n        </li>\n        <li>Optimization: 'CamelUnderlineConvert' now supports timestamp-dateTime convert, select the text and use shortcut `alt` + `shift` + `cmd` + `U` to find out.<br> </li>\n        </ul>\n        </br>\n        <li><h1>3.1</h1></li>\n        <ul>\n        <li>BugFix:<br>\n            <ul>\n            <li>Fix config item 'locale' problem when selected as 'ZN', and before before the 3.0 version's comment was English default.</li>\n            <li>Fix SQL definition in x.sql file.️</li>\n            <li>Fix batch insert records in xMapper.xml file cause 'id', 'createTime', 'updateTime' all should according to the Database.</li>\n            </ul>\n        </li>\n        <li>Optimization: Config item 'autoDetectSQLTimeColumn' now is more intelligent. If you checked, 'createTime' and 'updateTime' would be generated perfectly in there right position.<br> </li>\n        </ul>\n        </br>\n        <li><h1>3.0</h1></li>\n        <ul>\n        <li>Addition:<br>\n            <ul>\n            <li>Grand celebration for 'D8gerAutoCode' getting his face! Now you can config the generated property parameters by setting GUI.</li>\n            <li>First, Open the configuration box to set the generation parameters, 'Preference' --> 'Other Settings' --> 'D8gerAutoCode'</li>\n            <li>Then, Check the file to be generated and choose the generation path, rewrite 'author'、'apiUrlPrefix' and 'locale', and click the button to save your configuration.</li>\n            </ul>\n        </li>\n        <li>Optimization: Support project level setting parameters for non-invasive, d8ger.properties should exist invisible.<br> </li>\n        <li>Adjustment: Remove the generate params by 'd8ger.properties' file, replace of D8gerAutoCode setting GUI.<br> </li>\n        </ul>\n        </br>\n        <li><h1>2.5</h1></li>\n        <ul>\n        <li>Addition:<br>\n            <ul>\n            <li>Add 'autoDetectSQLTimeColumn' configuration for supporting disable default generating 'create_time' and 'update_time' column definition in SQL.</li>\n            <li>Add 'mapperBatterThenRepository' configuration for supporting custom mapper annotation in both SpringMVC and SpringBoot.</li>\n            <li>Add 'selectOneByExample' in Mapper.java for supporting query one record.</li>\n            <li>Add 'insertSelectiveWithId' in Mapper.java for supporting insert non null field and the null field will be filled with the database default value.</li>\n            </ul>\n        </li>\n        <li>Optimization: 'cause 'id' is the primary key, all insert operations should exclude 'id' column.<br> </li>\n        <li>BugFix:<br>\n            <ul>\n            <li>Generation 'update_time' column definition remove the rare comma.</li>\n            <li>Troubleshooting the rare dir named 'D8gerAutoCode', now you can see it only with unspecified directory configuration.</li>\n            </ul>\n        </li>\n        <li>Adjustment: Remove 'ServiceInterface' and 'ServiceImpl', 'cause I think 'Handler' is more suitable.<br> </li>\n        </ul>\n        </br>\n        <li><h1>2.4</h1></li>\n        <ul>\n        <li>Addition: One-click to beauty MySQL, isn't fragrant?<br> </li>\n        <li>Optimization: String parsing performance.<br> </li>\n        <li>Attention: Select your MySQL text, ctrl + alt + shift + 'B' will back a surprise.<br> </li>\n        </ul>\n        </br>\n        <li><h1>2.3</h1></li>\n        <ul>\n        <li>BugFix: Json format bug.</li>\n        <li>Addition:<br>\n            <ul>\n            <li>NASA easter eggs, try to type 'nasa' in the blank file in IDEA to get the nasa-template.</li>\n            <li>NASA easter eggs, multi-lines can be batch handled with the nasa-template, special for sql columns.</li>\n            </ul>\n        </li>\n        <li>Optimization: <br>\n            <ul>\n            <li>Optimize some regex performance.</li>\n            <li>Support linebreak or comma as the delimiter.</li>\n            <li>Support windows linebreak when rendering origin code.</li>\n            </ul>\n        </li>\n        <li>Attention: When execute auto-coding, you should be careful at the linebreak, it maybe different from your project config.</li>\n        <li>Adjustment: <br>\n            <ul>\n            <li>Icons changed for align, friendly view etc.</li>\n            <li>The manual of this plugin has been moved to my <a href=\"http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/\">website</a>.</li>\n            </ul>\n        </li>\n        </ul>\n        </br>\n        <li><h1>2.1</h1></li>\n        <ul>\n        <li>BugFix: add Uncapitalize, and the circle is Camel-Underline-Uppercase-Uncapitalize-Lowercase.</li>\n        <li>Optimization: Optimize some regex performance.</li>\n        <li>Attention: Regex easter eggs add some very useful regex search-replace skills hidden in JetBrains' IDE products. Try to learn and you will save much time at working.</li>\n        </ul>\n        </br>\n        <li><h1>2.0</h1></li>\n        <ul>\n        <li>BugFix: Modify method name in Controller.java.</li>\n        <li>Addition:<br>\n            <ul>\n            <li>Remove repeat work of moving file into directories for smart coding.</li>\n            <li>Camel-Underline-Uppercase-Lowercase can be converted to each other by shortcut `alt` + `shift` + `cmd` + `U`.</li>\n            <li>Regex easter eggs, try to type 'regex' in the blank file in IDEA to find it.</li>\n            </ul>\n        </li>\n        <li>Optimization: Optimize source code and improve performance.</li>\n        <li>Attention: If the icon of plugin shows error(red square with a cross), try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*).</li>\n        </ul>\n        </br>\n        <li><h1>1.24</h1></li>\n        <ul>\n        <li>BugFix: Update method named 'updateBatchByPrimaryKeySelective' in mapper.xml.</li>\n        <li>Addition: Set default language English and you can config it as Chinese Simplified, as before, typing 'd8ger' for the latest configuration template.</li>\n        <li>Attention: You should configure your database connection like 'allowMultiQueries=true' for supporting batchUpdate operation.</li>\n        </ul>\n        </br>\n        <li><h1>1.23</h1></li>\n        <ul>\n        <li>BugFix: Fix required dependencies by JetBrains' suggestion for some known compatibility issues.</li>\n        <li>Addition: Add JSON-formatter and WhiteChar-cleaner.</li>\n        <li>Attention: Can you star the project on the github?</li>\n        </ul>\n        </br>\n        <li><h1>1.22</h1></li>\n        <ul>\n        <li>BugFix: Fix README of style, description, picture problems.</li>\n        <li>Enhance: Enhance profile for generating codes by using regex to replace the circle of matching string.</li>\n        <li>Attention: Can you star the project on the github?</li>\n        </ul>\n        </br>\n        <li><h1>1.21</h1></li>\n        <ul>\n        <li>BugFix: Fix README of style, description, picture problems.</li>\n        <li>Addition: Add MoExample autoCoding for supporting simple sql.</li>\n        <li>Attention: Can you star the project on the github?</li>\n        </ul>\n        </br>\n        <li><h1>1.20</h1></li>\n        <ul>\n        <li>Completion: Auto coding for Mo/Example/Mapper/Xml/SQL/Service completed, wow!</li>\n        <li>Attention: Can you star the project on the github?</li>\n        </ul>\n        ]]>\n    </change-notes>\n</idea-plugin>"
  },
  {
    "path": "src/main/resources/icons/Icon",
    "content": "[阿里icon](https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=991968)\n\n[图片压缩](https://tinypng.com/)\n\n0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions\nUsage, static pattern can improve performance in regex searching:\n    public static final Pattern XXX_REGEX = Pattern.compile(\"...Regex string...\");\n\n1.Whitespace Regex\n(?:(?:(?:((?:\\s)+)|(?:(?:\\\\n)+)|(?:(?:\\\\r\\\\n)+)|(?:(?:\\\\t)+))))\n\n2.One or more newlines Regex\n(?:\\\\n|(?:\\\\r\\\\n))+\n\n3.Phone validate Regex\n^1[0-9]{10}$\n\n4.Email validate Regex\n^([a-z0-9A-Z]+[-|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\.)+[a-zA-Z]{2,}$\n\n5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species\n^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_]+$)(?![a-z0-9]+$)(?![a-z\\\\W_]+$)(?![0-9\\\\W_]+$)[a-zA-Z0-9\\\\W_]{8,30}$\n\n6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital]\n(?:position)(?:\\\\s)*(?:\\\\=)(?:\\\\s)*(?:\\\\d)*\n\n7.No '_' in word Regex\n^(?!_)[a-zA-Z0-9\\\\W]+$\n\n8.No upper case in word Regex\n^(?![A-Z])[a-z0-9\\\\W_]+$\n\n9.No lower case in word Regex\n^(?![a-z])[A-Z0-9\\\\W_]+$\n\n10.'www' Url detect Regex\n^(?:http)(?:s)?(?:\\:\\/\\/)(?:www\\.)?(?:[^\\ ]*)$"
  },
  {
    "path": "src/main/resources/template/.zshrc",
    "content": "export ZSH=\"$HOME/.oh-my-zsh\"\nexport HOMEBREW_NO_AUTO_UPDATE=true\n\nZSH_THEME=\"powerlevel9k/powerlevel9k\"\nPOWERLEVEL9K_MODE=\"nerdfont-complete\"\nPOWERLEVEL9K_PROMPT_ON_NEWLINE=true\nPOWERLEVEL9K_RPROMPT_ON_NEWLINE=false\nPOWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon user dir_writable dir vcs)\nPOWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time root_indicator background_jobs time disk_usage ram)\n#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\"%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )\"\n#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\"\"\n#POWERLEVEL9K_USER_ICON=\"\\uF415\" # \nPOWERLEVEL9K_ROOT_ICON=\"\\uF09C\"\n#POWERLEVEL9K_SUDO_ICON=$'\\uF09C' # \nPOWERLEVEL9K_TIME_FORMAT=\"%D{%H:%M}\"\n#POWERLEVEL9K_VCS_GIT_ICON='\\uF408 '\n#POWERLEVEL9K_VCS_GIT_GITHUB_ICON='\\uF408 '\n\nZSH_DISABLE_COMPFIX=true\n#ENABLE_CORRECTION=\"true\"\nDISABLE_CORRECTION=true\nCOMPLETION_WAITING_DOTS=true\n\n# 左侧栏目显示的要素（指定的关键字参考官网）\n#POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon context dir vcs)\n# 右侧栏目显示的要素\n#POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs time virtualenv)\n#新起一行显示命令 (推荐！极其方便）\n#POWERLEVEL9K_PROMPT_ON_NEWLINE=true\n#右侧状态栏与命令在同一行\n#POWERLEVEL9K_RPROMPT_ON_NEWLINE=false\n#缩短目录层级\n#POWERLEVEL9K_SHORTEN_DIR_LENGTH=1\n#缩短目录策略：隐藏上层目录中间的字\n#POWERLEVEL9K_SHORTEN_STRATEGY=\"truncate_middle\"\n#添加连接上下连接箭头更方便查看\n#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\"↱\"\n#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\"↳ \"\n# 新的命令与上面的命令隔开一行\n#POWERLEVEL9K_PROMPT_ADD_NEWLINE=true\n# Git仓库状态的色彩指定\n#POWERLEVEL9K_VCS_CLEAN_FOREGROUND='blue'\n#POWERLEVEL9K_VCS_CLEAN_BACKGROUND='black'\n#POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND='yellow'\n#POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='black'\n#POWERLEVEL9K_VCS_MODIFIED_FOREGROUND='red'\n#POWERLEVEL9K_VCS_MODIFIED_BACKGROUND='black'\n\n\nDISABLE_AUTO_UPDATE=\"true\"\n# autojump   : 'j'历史目录\n# cp         : 'cpv'带进度条的复制\n# zsh_reload : 'src'快速重载.zshrc\n# 快速编辑.zshrc: alias 'vrc=vim ~/.zshrc'\n# 快速展示.zshrc: alias 'crc=cat ~/.zshrc'\n# extract    : 'x'解压任何文件\nplugins=(git autojump cp zsh_reload extract zsh-syntax-highlighting)\n\nexport LC_ALL=en_US.UTF-8  \nexport LANG=en_US.UTF-8\n\n# Maven家目录\nexport M2_HOME=/usr/local/maven-3.6.1/apache-maven-3.6.1\nalias mcf=\"/usr/local/maven-3.6.1/caofanCPU-apache-maven-3.6.1/bin/mvn\"\n\n# 查看java安装位置命令 /usr/libexec/java_home -V\nexport JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home\nexport JRE_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre\nexport CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH\nexport PATH=$M2_HOME/bin:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH\n\n# Python项目打包工具包\nexport TWINE_HOME=/Users/D8GER/Library/Python/3.7\nexport PATH=$PATH:$TWINE_HOME/bin\n\nexport PATH=$PATH:$HOME/bin\nexport PATH=\"$PATH:/usr/local/python3/bin\"\n\n# thefuck插件\neval \"$(thefuck --alias)\"\n\n# 服务器\nalias caofanCPU='sshpass -f PWD_DIR  ssh  xxxx@xx.xx.xx.xx'\nalias caofanJumpAli='sshpass -f PWD_DIR  ssh  xx@xx.xx.xx.xx'\n\nfunction execute() {\n    http --session=~/Desktop/ssoLogin/session-${1}.json --verify=no -v ${2} POST ${@:3}\n}\n\nfunction downLoadResponse() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n}\n\nfunction downLoadExcel() {\n    echo \"执行命令内容: \\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\"\n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\n}\n\nfunction downloadD8ger() {\n    echo \"执行命令内容: 并发下载文件\"\n    for i in {1..30}\n        do \n            http --verify=no -v --download  GET  ${1} -o D8.zip\n    done\n}\n\nfunction show() {\n    echo \"执行命令内容: \\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\\n\"\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n}\n\nfunction searchPortOccupy(){\n    lsof -i :${1}\n}\n\nfunction searchPID(){\n    ps aux | grep ${1} | grep -v grep | awk '{print $2}'\n}\n\nfunction killPID(){\n    pid=`ps aux | grep ${1} | grep -v grep | awk '{print $2}'`\n    if [ -n \"$pid\" ]; then\n        kill -9 $pid\n        sleep 1\n    fi\n}\n\n\n# 环境\nfunction xDev() {\n    sshpass -f ENV_PIR.txt  ssh xx@xx.xx.xx.${1}  -t  'cd /work/www/d8ger.com/logs/; exec $SHELL'\n}\n\n# 环境普通模式\nfunction xDevNormal(){\n    sshpass -f ENV_PIR.txt  ssh xx@xx.xx.xx.${1}\n}\n\n# 不同环境\nfunction backgroundENV() {\n    env=${1}\n    if [ -z \"$env\" ]; then\n        echo \"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\"\n        return\n    fi\n    domain=''\n    if [ \"$env\" = '1' ]; then\n        domain='https://1.d8ger.com'\n    elif [ \"$env\" = '2' ]; then\n        domain='https://2.d8ger.com'\n    elif [ \"$env\" = '3' ]; then\n        domain='https://3.d8ger.com'\n    elif [ \"$env\" = '4' ]; then\n        domain='https://4.d8ger.com'\n    elif [ \"$env\" = '5' ]; then\n        domain='https://5.d8ger.com'\n    elif [ \"$env\" = '6' ]; then\n        domain='https://6.d8ger.com'\n    elif [ \"$env\" = '7' ]; then\n        domain='https://7.d8ger.com'\n    elif [ \"$env\" = '8' ]; then\n        domain='https://8.d8ger.com'\n    elif [ \"$env\" = '9' ]; then\n        domain='https://9.d8ger.com'\n    elif [ \"$env\" = '10' ]; then\n        domain='https://ok.d8ger.com'\n    fi\n    # 判断\n    if [ -z \"$domain\" ]; then\n        echo \"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\"\n        return\n    fi\n    echo \"德玛西亚, http -v --verify=no POST  ${domain}/ok/xx\"\n    echo \"查询任务是否启动及是否完成: grep \\\"德玛西亚\\\" all.log | grep \\\"end\\\"\"\n    http -v --verify=no POST  ${domain}/ok/xx\n}\n\nfunction justDoIT(){\n    SID=${1}\n    if [ -z \"$SID\" ]; then\n        echo \"非法的SID, 请检查\"\n        return\n    fi    \n    url=\"https://1.d8ger.com/xx/yy/zz\"\n    # 登录\n    login-cookie -f ~/Desktop/ssoLogin/sso-on-admin.json -a 6 \n    # 执行\n    echo \"执行:\\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\\n\"\n    # http多个参数不能放在一个字符串中, 用多个变量来区分解决\n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\n}\n\nfunction cph(){\n    echo \",------.   ,---.  ,----.   ,------.,------.\"\n    echo \"|  .-.  \\\\ |  o  |'  .-./   |  .---'|  .--. '\"\n    echo \"|  |  \\\\  :.'   '.|  | .---.|  \\`--, |  '--'.'\"\n    echo \"|  '--'  /|  o  |'  '--'  ||  \\`---.|  |\\\\  \\\\\"\n    echo \"\\`-------'  \\`---'  \\`------' \\`------'\\`--' '--'\"\n    echo \"##### SCP命令 #####\"\n    echo \"# -r 支持复制目录及其子文件\"\n    echo \"- 本地文件传到远程服务器\"\n    echo \"scp /X_DIR/LEARN-SH.sh  xx@xx.xx.xx.xx:~/\"\n    echo \"- 从远程服务器拉取文件\"\n    echo \"scp xx@xx.xx.xx.xx:~/HAHA.tmp /X_DIR/ZZ.xls\"\n    echo \"- 无痕登录\"\n    echo \"xD8scp || d8scp\"\n    echo \"sshpass -f /X_DIR/PWD-SSH.txt scp /X_DIR/LEARN-SH.sh  xx@xx.xx.xx.xx:~/\"\n    echo \"sshpass -f /X_DIR/PWD-SSH.txt scp xx@xx.xx.xx.xx:~/HAHA.tmp /X_DIR/ZZ.xls\"\n    echo \"##### cpv #####, zsh的一个插件cp, 文件复制时展示进度条\"\n    echo \"##### sudo cp #####, 普通复制\"\n}\n\nfunction fkgrep(){\n    echo \",------.,--. ,--. ,----.   ,------. ,------.,------.\"\n    echo \"|  .---'|  .'   /'  .-./   |  .--. '|  .---'|  .--. '\"\n    echo \"|  \\`--, |  .   ' |  | .---.|  '--'.'|  \\`--, |  '--' |\"\n    echo \"|  |\\`   |  |\\\\   \\'  '--'  ||  |\\\\  \\\\ |  \\`---.|  | --'\"\n    echo \"\\`--'    \\`--' '--' \\`------' \\`--' '--'\\`------'\\`--'\"\n    echo \"\"\n    echo \"grep -n '[a-zA-Z0-9]D8' X.txt\"\n    echo \"grep -n '[^a-zA-Z0-9]D9' X.txt\"\n    echo \"grep -n '^[a-z]' X.txt\"\n    echo \"grep -n '^[^a-z]' X.txt\"\n    echo \"grep -n '^$' X.txt\"\n    echo \"grep -n '\\.$' X.txt\"\n    echo \"grep -n 'g.*d' X.txt\"\n    echo \"grep -n 'go*d' X.txt\"\n    echo \"grep -n 'o\\{2,3\\}' X.txt\"\n    echo \"grep -En 'God|The'  X.txt     grep -n 'god\\|The' X.txt\"\n    echo \"grep -En 'o+' X.txt           grep -n 'o\\+' X.txt\"\n    echo \"grep -n '\\.' X.txt            grep -En '\\.' X.txt\"\n    echo \"grep -En '(oo)+' X.txt        grep -n '\\(oo\\)\\+' X.txt\"\n    echo \"Search Today's log: ll -ah | grep \\\"[a-z_A-Z]\\+\\.log\\\"\"\n}\n\nfunction arthasHelp(){\n    echo \"  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.\"\n    echo \" /  O  \\\\ |  .--. ''--.  .--'|  '--'  | /  O  \\\\ '   .-'\"\n    echo \"|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |\\`.  \\`-.\"\n    echo \"|  | |  ||  |\\\\  \\\\    |  |   |  |  |  ||  | |  |.-'    |\"\n    echo \"\\`--' \\`--'\\`--' '--'   \\`--'   \\`--'  \\`--'\\`--' \\`--'\\`-----'\"\n    # `和\\ 为特殊字符, 必须使用\\转义\n    echo \"\\n# 观察方法返回值\"\n    echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\" -x 2\"\n    echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\"\"\n    echo \"# 观察方法入参, 对象层次限制2级\"\n    echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\" -x 2 -b\"\n    echo \"# 持续记录3次接口调用\"\n    echo \"tt -t -n 3 com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage\"\n    echo \"# 展示记录接口调用的列表\"\n    echo \"tt -l\"\n    echo \"# 展示某个具体调用过程\"\n    echo \"tt -i 1002\"\n    echo \"# 重复某个具体调用, 重复3次, 重复间隔2秒\"\n    echo \"tt -i 1002 -p --replay-times 3  --replay-interval 2000\"\n    echo \"# 日志器\"\n    echo \"logger\"\n    echo \"# 类加载器列表\"\n    echo \"classloader -t\"\n    echo \"history\"\n    echo \"help\"\n    echo \"keymap\"\n    echo \"dashboard\"\n    echo \"# 清屏\"\n    echo \"cls\"\n    echo \"# 线程\"\n    echo \"thread\"\n    echo \"thread --state WAITING\"\n    echo \"thread --state TIMED_WAITING\"\n    echo \"thread --state RUNNABLE\"\n    echo \"\\n# 退出、关闭等命令, 禁止ctrl + C\"\n    echo \"# 退出某个命令\"\n    echo \"Q\"\n    echo \"# 退出当前arthas-client\"\n    echo \"quit\"\n    echo \"# 关闭arthas-server\"\n    echo \"shutdown\"\n}\n\nalias searchPID='searchPID'\nalias killPID='killPID'\nalias searchPortOccupy='searchPortOccupy'\nalias https-downLoadResponse='downLoadResponse'\nalias https-show='show'\nalias https-downLoadExcel='downLoadExcel'\nalias https-downloadD8ger='downloadD8ger'\n\nalias 'xDev=xDev'\nalias 'xDevNormal=xDevNormal'\nalias 'backgroundENV=backgroundENV'\n\nalias 'showssh=ps -ef | grep ssh'\nalias 'tsm=justDoIT'\n# 开隧道\nalias 'iphone4j=nohup sshpass -f TUNNEL_DIR ssh xx@xx.xx.xx.xx -L 11186:xx.xx.xx.xx:1186 -N &'\nalias 'ip=ifconfig | grep xxx'\n\nalias 'cph=cph'\nalias 'fkgrep=fkgrep'\nalias 'arthasHelp=arthasHelp'\n# 快速编辑.zshrc\nalias 'vrc=vim ~/.zshrc'\n# 快速展示.zshrc\nalias 'crc=cat ~/.zshrc'\n\n# source ~/.bash_profile\nif [ -f ~/.bash_profile ]; then\n    . ~/.bash_profile;\nfi\n\n\nsource $ZSH/oh-my-zsh.sh\n"
  },
  {
    "path": "src/main/resources/template/ControllerTemplate.txt",
    "content": "package @controllerPackage@;\n\nimport @handlerPackage@.@MoName@Handler;\nimport @moPackage@.@MoName@Mo;\nimport @swaggerMoPackage@.@MoName@Vo;\nimport com.alibaba.fastjson.JSONObject;\nimport com.github.pagehelper.PageInfo;\nimport com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\nimport com.github.xiaoymin.knife4j.annotations.ApiSort;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\nimport javax.validation.Valid;\nimport javax.validation.constraints.NotEmpty;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @MoName@Mo控制器\n *\n * @author @d8Author@\n */\n@RestController\n@Api(tags = {\"@MoName@Mo模块接口\"})\n@ApiSort(0)\n@Slf4j\npublic class @MoName@Controller {\n\n    @Resource\n    private @MoName@Handler @uncapitallizeMoName@Handler;\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\")\n    @ApiOperationSupport(order = 1)\n    @ApiOperation(value = \"@MoName@Mo新增记录\")\n    public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // 转换数据\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\n        return @uncapitallizeMoName@Mo.getId();\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\")\n    @ApiOperationSupport(order = 2)\n    @ApiOperation(value = \"@MoName@Mo批量新增\")\n    public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n        List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n        for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\n            @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\n        }\n        return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\")\n    @ApiOperationSupport(order = 3)\n    @ApiOperation(value = \"@MoName@Mo列表查询\")\n    public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // 转换数据\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\")\n    @ApiOperationSupport(order = 4)\n    @ApiOperation(value = \"@MoName@Mo分页查询\")\n    public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // 转换数据\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\n        return PageInfo.of(result@MoName@MoList);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\")\n    @ApiOperationSupport(order = 5)\n    @ApiOperation(value = \"@MoName@Mo修改记录\")\n    public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // 转换数据\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\")\n    @ApiOperationSupport(order = 5)\n    @ApiOperation(value = \"@MoName@Mo批量修改记录\")\n    public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n        // 转换数据\n        List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n        @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\n        return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\")\n    @ApiOperationSupport(order = 6)\n    @ApiOperation(value = \"@MoName@Mo删除记录\")\n    public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/resources/template/DeletedServiceInterfaceTemplate.txt",
    "content": "package @serviceInterfacePackage@;\n\nimport @moPackage@.@MoName@Mo;\nimport java.util.List;\n\n/**\n * @MoName@Mo对应的Service接口定义\n *\n * @author @d8Author@\n */\npublic interface @MoName@Service {\n\n    /**\n     * 插入单条记录\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int add(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * 批量插入\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * 查询列表, 如果携带分页参数则返回分页后的列表\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param pageParams 可选分页参数\n     * @return\n     */\n    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams);\n\n    /**\n     * 根据id更新非null字段\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * 批量根据id更新非null字段\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * 根据id物理删除\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> int delete(T id);\n\n}"
  },
  {
    "path": "src/main/resources/template/EN/ControllerTemplate.txt",
    "content": "package @controllerPackage@;\n\nimport @handlerPackage@.@MoName@Handler;\nimport @moPackage@.@MoName@Mo;\nimport @swaggerMoPackage@.@MoName@Vo;\nimport com.alibaba.fastjson.JSONObject;\nimport com.github.pagehelper.PageInfo;\nimport com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\nimport com.github.xiaoymin.knife4j.annotations.ApiSort;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\nimport javax.validation.Valid;\nimport javax.validation.constraints.NotEmpty;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @MoName@MoController\n *\n * @author @d8Author@\n */\n@RestController\n@Api(tags = {\"@MoName@Mo-ModuleAPI\"})\n@ApiSort(0)\n@Slf4j\npublic class @MoName@Controller {\n\n    @Resource\n    private @MoName@Handler @uncapitallizeMoName@Handler;\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\")\n    @ApiOperationSupport(order = 1)\n    @ApiOperation(value = \"@MoName@Mo-AddRecord\")\n    public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // convert Vo to Mo\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\n        return @uncapitallizeMoName@Mo.getId();\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\")\n    @ApiOperationSupport(order = 2)\n    @ApiOperation(value = \"@MoName@Mo-BatchAddRecords\")\n    public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n        List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n        for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\n            @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\n        }\n        return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\")\n    @ApiOperationSupport(order = 3)\n    @ApiOperation(value = \"@MoName@Mo-QueryList\")\n    public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // convert Vo to Mo\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\")\n    @ApiOperationSupport(order = 4)\n    @ApiOperation(value = \"@MoName@Mo-QueryListWithPaging\")\n    public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // convert Vo to Mo\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\n        return PageInfo.of(result@MoName@MoList);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\")\n    @ApiOperationSupport(order = 5)\n    @ApiOperation(value = \"@MoName@Mo-UpdateRecord\")\n    public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        // convert Vo to Mo\n        @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n        return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\")\n    @ApiOperationSupport(order = 5)\n    @ApiOperation(value = \"@MoName@Mo-BatchUpdateRecords\")\n    public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n        // convert Vo to Mo\n        List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n        @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\n        return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\n    }\n\n    @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\")\n    @ApiOperationSupport(order = 6)\n    @ApiOperation(value = \"@MoName@Mo-DeleteRecord\")\n    public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n        return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/resources/template/EN/D8GER.txt",
    "content": "# The default author called 'D8ger', but it's highly recommended to modify\nauthor=D8ger\n\n#### Basic generate, support two item configs such as:\n#### autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\n#### ATTENTION: if you config directory path, you should make sure it exists first\n#### WARNING: if you config error, the auto code file will put into the origin directory named 'D8AutoCode'\n#### THEN plugin will create Mo.java file\n#### AND put the file into 'com.xyz.caofancpu.d8ger.test.mo' directory\n#### UNDER current project source directory which include '/src/main/java'\nautoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\nautoCreateMapper=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper\nautoCreateExample=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper/Example\nautoCreateXML=true, /src/main/resources/mybatis\nautoCreateDefinitionSQL=true, /doc\n\n#### Enhance generate, also support two item configs, please refer Basic generate\nautoCreateSwaggerMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Vo\nautoCreateHandler=true, /src/main/java/com/xyz/caofancpu/d8ger/test/handler\nautoCreateController=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Controller\n\n#### Other normal binary config\nautoFormatStyle=true\n\n#### Api path prefix\n# apiUrlPrefix=/D8ger\n\n#### auto generating create_time and update_time SQL column definition\nautoDetectSQLTimeColumn=true\n\n#### if true then moMapper with annotation @Mapper, otherwise, with annotation @Repository\nmapperBatterThenRepository=true\n\n#### Language just for EN(English) and ZN(Chinese Simplified)\n# locale=ZN\n"
  },
  {
    "path": "src/main/resources/template/EN/DeletedServiceInterfaceTemplate.txt",
    "content": "package @serviceInterfacePackage@;\n\nimport @moPackage@.@MoName@Mo;\nimport java.util.List;\n\n/**\n * @MoName@MoService Interface Definition\n *\n * @author @d8Author@\n */\npublic interface @MoName@Service {\n\n    /**\n     * Insert a record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int add(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * Batch insert records\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * Query list, if the paging parameter is carried, return the list after paging\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param pageParams Optional paging parameters\n     * @return\n     */\n    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams);\n\n    /**\n     * Update non-null fields by ID for a record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * Batch Update non-nulls field by ID for multi-records\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * Delete a record by ID\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> int delete(T id);\n\n}"
  },
  {
    "path": "src/main/resources/template/EN/ExampleTemplate.txt",
    "content": "package @moExamplePackage@;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @MoName@Mo with multi-conditions object, Example\n *\n * @author @d8Author@\n */\npublic class @MoName@Example {\n\n    protected String orderByClause;\n\n    protected Integer limit;\n\n    protected boolean distinct;\n\n    protected List<Criteria> conditionCriteria;\n\n    public @MoName@Example() {\n        conditionCriteria = new ArrayList<>();\n    }\n\n    public @MoName@Example andOrderByClause(String orderByClause) {\n        this.orderByClause = orderByClause;\n        return this;\n    }\n\n    public String getOrderByClause() {\n        return orderByClause;\n    }\n\n    public @MoName@Example andLimit(Integer limit) {\n        if (limit != null && limit > 0) {\n            this.limit = limit;\n        }\n        return this;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public @MoName@Example andDistinct(boolean distinct) {\n        this.distinct = distinct;\n        return this;\n    }\n\n    public boolean isDistinct() {\n        return distinct;\n    }\n\n    public List<Criteria> getConditionCriteria() {\n        return conditionCriteria;\n    }\n\n    public void or(Criteria criteria) {\n        conditionCriteria.add(criteria);\n    }\n\n    public Criteria or() {\n        Criteria criteria = createCriteriaInternal();\n        conditionCriteria.add(criteria);\n        return criteria;\n    }\n\n    public Criteria createCriteria() {\n        Criteria criteria = createCriteriaInternal();\n        if (conditionCriteria.size() == 0) {\n            conditionCriteria.add(criteria);\n        }\n        return criteria;\n    }\n\n    protected Criteria createCriteriaInternal() {\n        return new Criteria();\n    }\n\n    public void clear() {\n        conditionCriteria.clear();\n        orderByClause = null;\n        distinct = false;\n    }\n\n    protected abstract static class GeneratedCriteria {\n        protected List<Criterion> criteria;\n\n        protected GeneratedCriteria() {\n            super();\n            criteria = new ArrayList<>();\n        }\n\n        public boolean isValid() {\n            return criteria.size() > 0;\n        }\n\n        public List<Criterion> getAllCriteria() {\n            return criteria;\n        }\n\n        public List<Criterion> getCriteria() {\n            return criteria;\n        }\n\n        protected void addCriterion(String condition) {\n            if (condition == null) {\n                throw new RuntimeException(\"Value for condition cannot be null\");\n            }\n            criteria.add(new Criterion(condition));\n        }\n\n        protected void addCriterion(String condition, Object value, String property) {\n            if (value == null) {\n                throw new RuntimeException(\"Value for \" + property + \" cannot be null\");\n            }\n            criteria.add(new Criterion(condition, value));\n        }\n\n        protected void addCriterion(String condition, Object value1, Object value2, String property) {\n            if (value1 == null || value2 == null) {\n                throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");\n            }\n            criteria.add(new Criterion(condition, value1, value2));\n        }\n\n@ExampleDefinitionMethod@\n    }\n\n    public static class Criteria extends GeneratedCriteria {\n        protected Criteria() {\n            super();\n        }\n    }\n\n    public static class Criterion {\n        private String condition;\n\n        private Object value;\n\n        private Object secondValue;\n\n        private boolean noValue;\n\n        private boolean singleValue;\n\n        private boolean betweenValue;\n\n        private boolean listValue;\n\n        private String typeHandler;\n\n        public String getCondition() {\n            return condition;\n        }\n\n        public Object getValue() {\n            return value;\n        }\n\n        public Object getSecondValue() {\n            return secondValue;\n        }\n\n        public boolean isNoValue() {\n            return noValue;\n        }\n\n        public boolean isSingleValue() {\n            return singleValue;\n        }\n\n        public boolean isBetweenValue() {\n            return betweenValue;\n        }\n\n        public boolean isListValue() {\n            return listValue;\n        }\n\n        public String getTypeHandler() {\n            return typeHandler;\n        }\n\n        protected Criterion(String condition) {\n            super();\n            this.condition = condition;\n            this.typeHandler = null;\n            this.noValue = true;\n        }\n\n        protected Criterion(String condition, Object value, String typeHandler) {\n            super();\n            this.condition = condition;\n            this.value = value;\n            this.typeHandler = typeHandler;\n            if (value instanceof List<?>) {\n                this.listValue = true;\n            } else {\n                this.singleValue = true;\n            }\n        }\n\n        protected Criterion(String condition, Object value) {\n            this(condition, value, null);\n        }\n\n        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\n            super();\n            this.condition = condition;\n            this.value = value;\n            this.secondValue = secondValue;\n            this.typeHandler = typeHandler;\n            this.betweenValue = true;\n        }\n\n        protected Criterion(String condition, Object value, Object secondValue) {\n            this(condition, value, secondValue, null);\n        }\n    }\n}"
  },
  {
    "path": "src/main/resources/template/EN/HandlerTemplate.txt",
    "content": "package @handlerPackage@;\n\nimport @mapperPackage@.@MoName@Mapper;\nimport @moPackage@.@MoName@Mo;\nimport com.github.pagehelper.PageHelper;\nimport org.springframework.stereotype.Service;\nimport lombok.extern.slf4j.Slf4j;\n\nimport javax.annotation.Resource;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * @MoName@Handler\n *\n * @author @d8Author@\n */\n@Service\n@Slf4j\npublic class @MoName@Handler {\n\n    @Resource\n    private @MoName@Mapper @uncapitallizeMoName@Mapper;\n\n    /**\n     * Insert a record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\n        return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * Batch insert records\n     * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n        return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\n    }\n\n    /**\n     * Query list, if the paging parameter is carried, return the list after paging\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param pageParams Optional paging parameters\n     * @return\n     */\n    public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\n        if (Objects.nonNull(pageParams) && pageParams.length > 0) {\n            int pageNum = pageParams[0];\n            int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\n            PageHelper.startPage(pageNum, pageSize);\n        }\n        return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * Update non-null fields by ID for a single record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\n        return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * Batch Update non-nulls field by ID for multi-records\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n        return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\n    }\n\n    /**\n     * Delete a record by ID\n     *\n     * @param id\n     * @return\n     */\n    public <T extends Number> int delete(T id) {\n        return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\n    }\n\n    /**\n     * Select a record by ID\n     *\n     * @param id\n     * @return\n     */\n    public <T extends Number> @MoName@Mo selectByPrimaryKey(T id) {\n        return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\n    }\n\n}"
  },
  {
    "path": "src/main/resources/template/EN/MapperTemplate.txt",
    "content": "package @mapperPackage@;\n\nimport @moExamplePackage@.@MoName@Example;\nimport @moPackage@.@MoName@Mo;\nimport org.apache.ibatis.annotations.Param;\nimport @MapperAnnotationPackage@;\n\nimport java.util.List;\n\n/**\n * @MoName@Mo Database Mapper\n *\n * @author @d8Author@\n */\n@MapperAnnotation@\npublic interface @MoName@Mapper {\n\n    /**\n     * Query list by criteria, supporting all conditions for querying a single table\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * Batch update non-null fields by ID for multi-records\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * Update non-null fields by ID for a single record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    int updateByExampleSelective(@Param(\"record\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\"example\") @MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * Delete a single record by condition\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * Statistical records by query conditions\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return Number of records\n     */\n    int countByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * Add a single record, and set the ID for the input Mo parameter\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * Batch add records, and set the ID for the input MoList parameters\n     * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * @MoName@ query list\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * Query just one record by ID\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> @MoName@Mo selectByPrimaryKey(T id);\n\n    /**\n     * Update non-null fields by ID for a single record\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * Delete a record by ID\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> int deleteByPrimaryKey(T id);\n\n    /**\n     * Query just one record by criteria, supporting all conditions for querying a single table\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * Add a single record with nonNull field, and set the ID for the input Mo parameter\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n\n}"
  },
  {
    "path": "src/main/resources/template/EN/MapperXMLTemplate.txt",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"@mapperPackage@.@MoName@Mapper\">\n\n    <!-- Conditions during query operation -->\n    <sql id=\"Example_Where_Clause\">\n        <where>\n            <foreach collection=\"conditionCriteria\" item=\"criteria\" separator=\"or\">\n                <if test=\"criteria.valid\">\n                    <trim prefix=\"(\" prefixOverrides=\"and\" suffix=\")\">\n                        <foreach collection=\"criteria.criteria\" item=\"criterion\">\n                            <choose>\n                                <when test=\"criterion.noValue\">\n                                    AND ${criterion.condition}\n                                </when>\n                                <when test=\"criterion.singleValue\">\n                                    AND ${criterion.condition} #{criterion.value}\n                                </when>\n                                <when test=\"criterion.betweenValue\">\n                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n                                </when>\n                                <when test=\"criterion.listValue\">\n                                    AND ${criterion.condition}\n                                    <foreach close=\")\" collection=\"criterion.value\" item=\"listItem\" open=\"(\" separator=\",\">\n                                        #{listItem}\n                                    </foreach>\n                                </when>\n                            </choose>\n                        </foreach>\n                    </trim>\n                </if>\n            </foreach>\n        </where>\n    </sql>\n\n    <!-- Conditions during update operation -->\n    <sql id=\"Update_By_Example_Where_Clause\">\n        <where>\n            <foreach collection=\"example.conditionCriteria\" item=\"criteria\" separator=\"or\">\n                <if test=\"criteria.valid\">\n                    <trim prefix=\"(\" prefixOverrides=\"and\" suffix=\")\">\n                        <foreach collection=\"criteria.criteria\" item=\"criterion\">\n                            <choose>\n                                <when test=\"criterion.noValue\">\n                                    AND ${criterion.condition}\n                                </when>\n                                <when test=\"criterion.singleValue\">\n                                    AND ${criterion.condition} #{criterion.value}\n                                </when>\n                                <when test=\"criterion.betweenValue\">\n                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n                                </when>\n                                <when test=\"criterion.listValue\">\n                                    AND ${criterion.condition}\n                                    <foreach close=\")\" collection=\"criterion.value\" item=\"listItem\" open=\"(\" separator=\",\">\n                                        #{listItem}\n                                    </foreach>\n                                </when>\n                            </choose>\n                        </foreach>\n                    </trim>\n                </if>\n            </foreach>\n        </where>\n    </sql>\n\n    <!-- 1.Query list by criteria -->\n    <select id=\"selectByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n        <if test=\"distinct\">\n            DISTINCT\n        </if>\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n        <if test=\"orderByClause != null\">\n            ORDER BY ${orderByClause}\n        </if>\n        <if test=\"limit != null\">\n            LIMIT ${limit}\n        </if>\n    </select>\n\n    <!-- 2.Batch update non-null fields by ID for multi-records -->\n    <update id=\"updateBatchByPrimaryKeySelective\" parameterType=\"java.util.List\">\n        <foreach collection=\"list\" open=\"\" close=\"\" separator=\";\" item=\"item\">\n            UPDATE `@mo_table_name@`\n            <set>\n@BatchUpdateNonNullFieldByID@\n            </set>\n            WHERE `id` = #{item.id}\n        </foreach>\n    </update>\n\n    <!-- 3.Update non-null fields by ID for a single record -->\n    <update id=\"updateByExampleSelective\" parameterType=\"map\">\n        UPDATE `@mo_table_name@`\n        <set>\n@UpdateNonNullFieldByExample@\n        </set>\n        <if test=\"_parameter != null\">\n            <include refid=\"Update_By_Example_Where_Clause\"/>\n        </if>\n    </update>\n\n    <!-- 4.Delete a single record by condition -->\n    <delete id=\"deleteByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\">\n        DELETE FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n    </delete>\n\n    <!-- 5.Statistical records by query conditions -->\n    <select id=\"countByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\">\n        SELECT\n            COUNT(*)\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n    </select>\n\n    <!-- 6.Add a single record, and return the ID -->\n    <insert id=\"insertWithId\" parameterType=\"@moPackage@.@MoName@Mo\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@` (\n@BaseColumnList@\n        )\n        values (\n@InsertField@\n        )\n    </insert>\n\n    <!-- 7.Batch add records, and return the IDs -->\n    <insert id=\"insertBatchWithId\" parameterType=\"java.util.List\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@` (\n@BaseColumnList@\n        )\n        VALUES\n        <foreach collection=\"list\" item=\"item\" separator=\",\">\n@BatchInsertField@\n        </foreach>\n    </insert>\n\n    <!-- 8.@MoName@ query list -->\n    <select id=\"query@MoName@MoList\" parameterType=\"@moPackage@.@MoName@Mo\"  resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        WHERE 1 = 1\n@MoListQuery@\n    </select>\n\n    <!-- 9.Query just one record by ID -->\n    <select id=\"selectByPrimaryKey\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        WHERE `id` = #{id}\n    </select>\n\n    <!-- 10.Update non-null fields by ID for a single record -->\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"@moPackage@.@MoName@Mo\">\n        UPDATE `@mo_table_name@`\n        <set>\n@UpdateNonNullFieldByID@\n        </set>\n        WHERE `id` = #{id}\n    </update>\n\n    <!-- 11.Delete a record by ID -->\n    <delete id=\"deleteByPrimaryKey\">\n        DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\n    </delete>\n\n    <!-- 12.Query just one record by criteria -->\n    <select id=\"selectOneByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n        <if test=\"distinct\">\n            DISTINCT\n        </if>\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n        <if test=\"orderByClause != null\">\n            ORDER BY ${orderByClause}\n        </if>\n        LIMIT 1\n    </select>\n\n    <!-- 13.Add a single record with nonNull field, and return the ID -->\n    <insert id=\"insertSelectiveWithId\" parameterType=\"@moPackage@.@MoName@Mo\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@`\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n@NonNullColumnList@\n        </trim>\n        <trim prefix=\"VALUES (\" suffix=\")\" suffixOverrides=\",\">\n@NonNullInsertField@\n        </trim>\n    </insert>\n</mapper>"
  },
  {
    "path": "src/main/resources/template/EN/MoTemplate.txt",
    "content": "package @moPackage@;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Date;\n\n/**\n * @MoName@Mo\n *\n * @author @d8Author@\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\npublic class @MoName@Mo {\n\n@field@\n\n}"
  },
  {
    "path": "src/main/resources/template/EN/SQLTemplate.txt",
    "content": "\n-- ----------------------------\n-- D8ger-Sql-Auto-Generated\n-- Table structure for `@mo_table_name@`\n-- @author @d8Author@\n-- ----------------------------\n-- DROP TABLE IF EXISTS `@mo_table_name@`;\nCREATE TABLE `@mo_table_name@`\n(\n@sql_column@\n)\n    comment '@MoName@' charset = utf8mb4;\n"
  },
  {
    "path": "src/main/resources/template/EN/SwaggerMoTemplate.txt",
    "content": "package @swaggerMoPackage@;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Date;\n\n/**\n * @MoName@Mo with SwaggerApi Enhance Vo\n *\n * @author @d8Author@\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\n@ApiModel\npublic class @MoName@Vo {\n\n@swaggerField@\n\n}"
  },
  {
    "path": "src/main/resources/template/END.txt",
    "content": "=========================================END=========================================\nNote: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\n      which these context included will be ignored;\n      2.Considering compatibility separator, Multi-lines to be handled\n      must include ',' or line break or '，' as the split keyword.\n      3.config example:\n      - @<alignStyle=LEFT>@    , LEFT(default) and you can config CENTER, RIGHT too\n      - @<algorithmType=1>@    , 1(default) as 'AES' and 2 as 'PinYin'\n      - @<operateType=2>@      , 1 as encrypt, 2 as decrypt\n                                 and 0(default) is encrypt + decrypt for complete\n      4.As example below, one handled what you will find like this:\n      When algorithmType=1 && operateType = 0\n        MyName -->(first AES encryption) d8gerX==\n               -->(then AES decryption)  MyName\n      When algorithmType=2 && operateType = 0\n        帝八哥  -->(first Fetch Chinese PinYin) dibage\n               -->(then PinYin encryption)     d8gerY==\n               -->(last PinYin decryption)     dibage\n      Other case, just refer the two above.\n=========================================END=========================================\nThe next line is very import below, do not modify anything or you'll get nothing\n@D8ger-END@\n\n\nAName"
  },
  {
    "path": "src/main/resources/template/ExampleTemplate.txt",
    "content": "package @moExamplePackage@;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @MoName@Mo对应的Example单表操作对象\n *\n * @author @d8Author@\n */\npublic class @MoName@Example {\n\n    protected String orderByClause;\n\n    protected Integer limit;\n\n    protected boolean distinct;\n\n    protected List<Criteria> conditionCriteria;\n\n    public @MoName@Example() {\n        conditionCriteria = new ArrayList<>();\n    }\n\n    public @MoName@Example andOrderByClause(String orderByClause) {\n        this.orderByClause = orderByClause;\n        return this;\n    }\n\n    public String getOrderByClause() {\n        return orderByClause;\n    }\n\n    public @MoName@Example andLimit(Integer limit) {\n        if (limit != null && limit > 0) {\n            this.limit = limit;\n        }\n        return this;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public @MoName@Example andDistinct(boolean distinct) {\n        this.distinct = distinct;\n        return this;\n    }\n\n    public boolean isDistinct() {\n        return distinct;\n    }\n\n    public List<Criteria> getConditionCriteria() {\n        return conditionCriteria;\n    }\n\n    public void or(Criteria criteria) {\n        conditionCriteria.add(criteria);\n    }\n\n    public Criteria or() {\n        Criteria criteria = createCriteriaInternal();\n        conditionCriteria.add(criteria);\n        return criteria;\n    }\n\n    public Criteria createCriteria() {\n        Criteria criteria = createCriteriaInternal();\n        if (conditionCriteria.size() == 0) {\n            conditionCriteria.add(criteria);\n        }\n        return criteria;\n    }\n\n    protected Criteria createCriteriaInternal() {\n        return new Criteria();\n    }\n\n    public void clear() {\n        conditionCriteria.clear();\n        orderByClause = null;\n        distinct = false;\n    }\n\n    protected abstract static class GeneratedCriteria {\n        protected List<Criterion> criteria;\n\n        protected GeneratedCriteria() {\n            super();\n            criteria = new ArrayList<>();\n        }\n\n        public boolean isValid() {\n            return criteria.size() > 0;\n        }\n\n        public List<Criterion> getAllCriteria() {\n            return criteria;\n        }\n\n        public List<Criterion> getCriteria() {\n            return criteria;\n        }\n\n        protected void addCriterion(String condition) {\n            if (condition == null) {\n                throw new RuntimeException(\"Value for condition cannot be null\");\n            }\n            criteria.add(new Criterion(condition));\n        }\n\n        protected void addCriterion(String condition, Object value, String property) {\n            if (value == null) {\n                throw new RuntimeException(\"Value for \" + property + \" cannot be null\");\n            }\n            criteria.add(new Criterion(condition, value));\n        }\n\n        protected void addCriterion(String condition, Object value1, Object value2, String property) {\n            if (value1 == null || value2 == null) {\n                throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");\n            }\n            criteria.add(new Criterion(condition, value1, value2));\n        }\n\n@ExampleDefinitionMethod@\n    }\n\n    public static class Criteria extends GeneratedCriteria {\n        protected Criteria() {\n            super();\n        }\n    }\n\n    public static class Criterion {\n        private String condition;\n\n        private Object value;\n\n        private Object secondValue;\n\n        private boolean noValue;\n\n        private boolean singleValue;\n\n        private boolean betweenValue;\n\n        private boolean listValue;\n\n        private String typeHandler;\n\n        public String getCondition() {\n            return condition;\n        }\n\n        public Object getValue() {\n            return value;\n        }\n\n        public Object getSecondValue() {\n            return secondValue;\n        }\n\n        public boolean isNoValue() {\n            return noValue;\n        }\n\n        public boolean isSingleValue() {\n            return singleValue;\n        }\n\n        public boolean isBetweenValue() {\n            return betweenValue;\n        }\n\n        public boolean isListValue() {\n            return listValue;\n        }\n\n        public String getTypeHandler() {\n            return typeHandler;\n        }\n\n        protected Criterion(String condition) {\n            super();\n            this.condition = condition;\n            this.typeHandler = null;\n            this.noValue = true;\n        }\n\n        protected Criterion(String condition, Object value, String typeHandler) {\n            super();\n            this.condition = condition;\n            this.value = value;\n            this.typeHandler = typeHandler;\n            if (value instanceof List<?>) {\n                this.listValue = true;\n            } else {\n                this.singleValue = true;\n            }\n        }\n\n        protected Criterion(String condition, Object value) {\n            this(condition, value, null);\n        }\n\n        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\n            super();\n            this.condition = condition;\n            this.value = value;\n            this.secondValue = secondValue;\n            this.typeHandler = typeHandler;\n            this.betweenValue = true;\n        }\n\n        protected Criterion(String condition, Object value, Object secondValue) {\n            this(condition, value, secondValue, null);\n        }\n    }\n}"
  },
  {
    "path": "src/main/resources/template/HandlerTemplate.txt",
    "content": "package @handlerPackage@;\n\nimport @mapperPackage@.@MoName@Mapper;\nimport @moPackage@.@MoName@Mo;\nimport com.github.pagehelper.PageHelper;\nimport org.springframework.stereotype.Service;\nimport lombok.extern.slf4j.Slf4j;\n\nimport javax.annotation.Resource;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * @MoName@Mo对应的Handler\n *\n * @author @d8Author@\n */\n@Service\n@Slf4j\npublic class @MoName@Handler {\n\n    @Resource\n    private @MoName@Mapper @uncapitallizeMoName@Mapper;\n\n    /**\n     * 插入单条记录\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\n        return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * 批量插入\n     * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n        return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\n    }\n\n    /**\n     * 查询列表, 如果携带分页参数则返回分页后的列表\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param pageParams 可选分页参数\n     * @return\n     */\n    public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\n        if (Objects.nonNull(pageParams) && pageParams.length > 0) {\n            int pageNum = pageParams[0];\n            int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\n            PageHelper.startPage(pageNum, pageSize);\n        }\n        return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * 根据id更新非null字段\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\n        return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\n    }\n\n    /**\n     * 批量根据id更新非null字段\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n        return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\n    }\n\n    /**\n     * 根据id物理删除\n     *\n     * @param id\n     * @return\n     */\n    public <T extends Number> int delete(T id) {\n        return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\n    }\n\n    /**\n     * 根据id查询单条记录\n     *\n     * @param id\n     * @return\n     */\n    public <T extends Number> @MoName@Mo selectByPrimaryKey(T id) {\n        return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\n    }\n\n}"
  },
  {
    "path": "src/main/resources/template/MapperTemplate.txt",
    "content": "package @mapperPackage@;\n\nimport @moExamplePackage@.@MoName@Example;\nimport @moPackage@.@MoName@Mo;\nimport org.apache.ibatis.annotations.Param;\nimport @MapperAnnotationPackage@;\n\nimport java.util.List;\n\n/**\n * @MoName@Mo对应的Mapper\n *\n * @author @d8Author@\n */\n@MapperAnnotation@\npublic interface @MoName@Mapper {\n\n    /**\n     * 根据条件查询列表\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * 批量更新, 根据主键更新非null字段\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * 根据条件更新非null字段\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    int updateByExampleSelective(@Param(\"record\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\"example\") @MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * 根据条件删除记录\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * 根据条件统计记录\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return 记录条数\n     */\n    int countByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * 增加单条记录, 并为入参设置ID\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * 批量增加记录, 并为入参设置ID\n     * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\n     *\n     * @param @uncapitallizeMoName@MoList\n     * @return\n     */\n    int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n\n    /**\n     * @MoName@列表查询\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * 根据ID查询对象\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> @MoName@Mo selectByPrimaryKey(T id);\n\n    /**\n     * 根据主键只更新非null字段\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\n\n    /**\n     * 根据ID删除记录\n     *\n     * @param id\n     * @return\n     */\n    <T extends Number> int deleteByPrimaryKey(T id);\n\n    /**\n     * 根据条件查询单个对象\n     *\n     * @param @uncapitallizeMoName@Example\n     * @return\n     */\n    @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\n\n    /**\n     * 增加单条非空字段记录, 并为入参设置ID\n     *\n     * @param @uncapitallizeMoName@Mo\n     * @return\n     */\n    int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n\n}"
  },
  {
    "path": "src/main/resources/template/MapperXMLTemplate.txt",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"@mapperPackage@.@MoName@Mapper\">\n\n    <!-- 查询操作时条件 -->\n    <sql id=\"Example_Where_Clause\">\n        <where>\n            <foreach collection=\"conditionCriteria\" item=\"criteria\" separator=\"or\">\n                <if test=\"criteria.valid\">\n                    <trim prefix=\"(\" prefixOverrides=\"and\" suffix=\")\">\n                        <foreach collection=\"criteria.criteria\" item=\"criterion\">\n                            <choose>\n                                <when test=\"criterion.noValue\">\n                                    AND ${criterion.condition}\n                                </when>\n                                <when test=\"criterion.singleValue\">\n                                    AND ${criterion.condition} #{criterion.value}\n                                </when>\n                                <when test=\"criterion.betweenValue\">\n                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n                                </when>\n                                <when test=\"criterion.listValue\">\n                                    AND ${criterion.condition}\n                                    <foreach close=\")\" collection=\"criterion.value\" item=\"listItem\" open=\"(\" separator=\",\">\n                                        #{listItem}\n                                    </foreach>\n                                </when>\n                            </choose>\n                        </foreach>\n                    </trim>\n                </if>\n            </foreach>\n        </where>\n    </sql>\n\n    <!-- 更新操作时条件 -->\n    <sql id=\"Update_By_Example_Where_Clause\">\n        <where>\n            <foreach collection=\"example.conditionCriteria\" item=\"criteria\" separator=\"or\">\n                <if test=\"criteria.valid\">\n                    <trim prefix=\"(\" prefixOverrides=\"and\" suffix=\")\">\n                        <foreach collection=\"criteria.criteria\" item=\"criterion\">\n                            <choose>\n                                <when test=\"criterion.noValue\">\n                                    AND ${criterion.condition}\n                                </when>\n                                <when test=\"criterion.singleValue\">\n                                    AND ${criterion.condition} #{criterion.value}\n                                </when>\n                                <when test=\"criterion.betweenValue\">\n                                    AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n                                </when>\n                                <when test=\"criterion.listValue\">\n                                    AND ${criterion.condition}\n                                    <foreach close=\")\" collection=\"criterion.value\" item=\"listItem\" open=\"(\" separator=\",\">\n                                        #{listItem}\n                                    </foreach>\n                                </when>\n                            </choose>\n                        </foreach>\n                    </trim>\n                </if>\n            </foreach>\n        </where>\n    </sql>\n\n    <!-- 1.根据条件查询列表 -->\n    <select id=\"selectByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n        <if test=\"distinct\">\n            DISTINCT\n        </if>\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n        <if test=\"orderByClause != null\">\n            ORDER BY ${orderByClause}\n        </if>\n        <if test=\"limit != null\">\n            LIMIT ${limit}\n        </if>\n    </select>\n\n    <!-- 2.批量更新, 根据主键更新非null字段 -->\n    <update id=\"updateBatchByPrimaryKeySelective\" parameterType=\"java.util.List\">\n        <foreach collection=\"list\" open=\"\" close=\"\" separator=\";\" item=\"item\">\n            UPDATE `@mo_table_name@`\n            <set>\n@BatchUpdateNonNullFieldByID@\n            </set>\n            WHERE `id` = #{item.id}\n        </foreach>\n    </update>\n\n    <!-- 3.根据条件更新非null字段 -->\n    <update id=\"updateByExampleSelective\" parameterType=\"map\">\n        UPDATE `@mo_table_name@`\n        <set>\n@UpdateNonNullFieldByExample@\n        </set>\n        <if test=\"_parameter != null\">\n            <include refid=\"Update_By_Example_Where_Clause\"/>\n        </if>\n    </update>\n\n    <!-- 4.根据条件删除记录 -->\n    <delete id=\"deleteByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\">\n        DELETE FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n    </delete>\n\n    <!-- 5.根据条件统计记录 -->\n    <select id=\"countByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\">\n        SELECT\n            COUNT(*)\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n    </select>\n\n    <!-- 6.增加单条记录, 返回主键 -->\n    <insert id=\"insertWithId\" parameterType=\"@moPackage@.@MoName@Mo\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@` (\n@BaseColumnList@\n        )\n        values (\n@InsertField@\n        )\n    </insert>\n\n    <!-- 7.批量增加记录, 返回主键 -->\n    <insert id=\"insertBatchWithId\" parameterType=\"java.util.List\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@` (\n@BaseColumnList@\n        )\n        VALUES\n        <foreach collection=\"list\" item=\"item\" separator=\",\">\n@BatchInsertField@\n        </foreach>\n    </insert>\n\n    <!-- 8.@MoName@列表查询 -->\n    <select id=\"query@MoName@MoList\" parameterType=\"@moPackage@.@MoName@Mo\"  resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        WHERE 1 = 1\n@MoListQuery@\n    </select>\n\n    <!-- 9.根据ID查询对象 -->\n    <select id=\"selectByPrimaryKey\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        WHERE `id` = #{id}\n    </select>\n\n    <!-- 10.根据主键只更新非null字段 -->\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"@moPackage@.@MoName@Mo\">\n        UPDATE `@mo_table_name@`\n        <set>\n@UpdateNonNullFieldByID@\n        </set>\n        WHERE `id` = #{id}\n    </update>\n\n    <!-- 11.根据ID删除记录 -->\n    <delete id=\"deleteByPrimaryKey\">\n        DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\n    </delete>\n\n    <!-- 12.根据条件查询单个对象 -->\n    <select id=\"selectOneByExample\" parameterType=\"@moExamplePackage@.@MoName@Example\" resultType=\"@moPackage@.@MoName@Mo\">\n        SELECT\n        <if test=\"distinct\">\n            DISTINCT\n        </if>\n@SelectBaseColumnList@\n        FROM `@mo_table_name@`\n        <if test=\"_parameter != null\">\n            <include refid=\"Example_Where_Clause\"/>\n        </if>\n        <if test=\"orderByClause != null\">\n            ORDER BY ${orderByClause}\n        </if>\n        LIMIT 1\n    </select>\n\n    <!-- 13.增加单条非空字段记录, 返回主键 -->\n    <insert id=\"insertSelectiveWithId\" parameterType=\"@moPackage@.@MoName@Mo\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        INSERT INTO `@mo_table_name@`\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n@NonNullColumnList@\n        </trim>\n        <trim prefix=\"VALUES (\" suffix=\")\" suffixOverrides=\",\">\n@NonNullInsertField@\n        </trim>\n    </insert>\n</mapper>"
  },
  {
    "path": "src/main/resources/template/MoTemplate.txt",
    "content": "package @moPackage@;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Date;\n\n/**\n * @MoName@Mo\n *\n * @author @d8Author@\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\npublic class @MoName@Mo {\n\n@field@\n\n}"
  },
  {
    "path": "src/main/resources/template/NASA.txt",
    "content": "=========================================NASA=========================================\nNote: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\n      which these context included will be ignored;\n      2.Multi-lines to be handled must include ','\n      as the split keyword\n      3.config example:\n      - @<prefix=D8(>@         , add 'D8(' before the start of each line\n      - @<suffix=)>@           , add ')' after the end of each line\n      - @<alignStyle=LEFT>@    , you can config CENTER, RIGHT too\n      - @<formatSQL=false>@    , if config SQL then it will append 'AS' alias name\n      - @<formatAsCamel=false>@ , special for SQL column alias camel name\n      4.As example below, one handled what you will find like this:\n      first_name,       --> D8(first_name)        AS  firstName,\n      current_age,      --> D8(current_age)       AS  currentAge,\n      blog_url,         --> D8(blog_url)          AS  blogUrl,\n      graduated_school, --> D8(graduated_school)  AS  graduatedSchool,\n      total_assets      --> D8(total_assets)      AS  totalAssets\n=========================================NASA=========================================\nThe next line is very import below, do not modify anything or you'll get nothing\n@D8ger-ALIGN@\n\n\nfirst_name,\ncurrent_age,\nblog_url,\ngraduated_school,\ntotal_assets\n\n\n"
  },
  {
    "path": "src/main/resources/template/PLAN.txt",
    "content": "- Redis\n    1.Redis常用数据结构: 理论+实践\n    2.Redis锁: 理论+实践\n    3.Redis缓存、队列、雪崩、击穿、热点、布隆过滤器, LRU, 单线程IO多路复用, 了解\n- RocketMQ\n    1.设计架构\n    2.部署架构\n    3.常见描述\n    4.实践问题\n- Kafka\n    1.原理\n- 工具\n    1.CollectionUtil, Stream底层原理, Fork/Join框架\n    2.DateUtil, LocalDateTime\n    3.WrapTreeUtil, 万能无侵入性, 平铺列表<->树形化\n    4.SpringBoot-Start\n- 算法\n    1.SkipList, TreeMap原理\n    2.Tarjan鉴环算法, 背景及代码示例\n    3.其他\n- 项目\n    1.用户系统重构, 拆分SSO\n    2.数据报告系统, 多线程任务计算框架\n    3.供应链金融\n    4.开源插件(软件命令初始化提示集成)"
  },
  {
    "path": "src/main/resources/template/Regex.txt",
    "content": "0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions\nUsage, static pattern can improve performance in regex searching:\n    public static final Pattern XXX_REGEX = Pattern.compile(\"...Regex string...\");\n\n1.Whitespace Regex\n((?:\\s)+)\n\n2.One or more newlines Regex\n(?:\\\\n|(?:\\\\r\\\\n))+\n\n3.Phone validate Regex\n^1[0-9]{10}$\n\n4.Email validate Regex\n^([a-z0-9A-Z]+[-|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\.)+[a-zA-Z]{2,}$\n\n5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species\n^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_]+$)(?![a-z0-9]+$)(?![a-z\\\\W_]+$)(?![0-9\\\\W_]+$)[a-zA-Z0-9\\\\W_]{8,30}$\n\n6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital]\n(?:position)(?:\\\\s)*(?:\\\\=)(?:\\\\s)*(?:\\\\d)*\n\n7.No '_' and begin with [A-Z] in word Regex\n^(?!_)(?:[A-Z])[a-zA-Z0-9\\\\W]+$\n\n8.No upper case in word Regex\n^(?![A-Z])[a-z0-9\\\\W_]+$\n\n9.No lower case in word Regex\n^(?![a-z])[A-Z0-9\\\\W_]+$\n\n10.'www' Url detect Regex\n^(?:http)(?:s)?(?:\\:\\/\\/)(?:www\\.)?(?:[^\\ ]*)$\n\n11.IDEA Skills\n- 11.1 For multi-lines, how to add some same fix characters?\n ResearchRegex@   (?:\\n|(?:\\r\\n))+\n ReplaceString@   ,\\r\\n\n\n- 11.2 For multi-lines, especially for SQL batch replacing, such as:\n    - zcy_cf,  --> WE'RE(zcy_cf) AS zcy_cf,\n    - cf_zcy   --> WE'RE(cf_zcy) AS cf_zcy\n    - note: WE'RE is just a function\n I.Clear the character ','\n  ResearchRegex@   (?:,)+\n  ReplaceString@   [EMPTY]\n II.Batch replace\n  ResearchRegex@   ((?:\\w+)+)\n  ReplaceString@   WE'RE($0) AS $0,\n III.Clear the rare character ',' at the last line\n\n- 11.3 For multi-lines, especially for SQL batch reduce-replacing, such as:\n    - WE'RE(zcy_cf) AS zcy_cf,  --> zcy_cf,\n    - WE'RE(cf_zcy) AS cf_zcy   --> cf_zcy\n    - note: WE'RE is just a function\n I.Handle prefix\n  ResearchRegex@   (?:WE'RE\\()+\n  ReplaceString@   [EMPTY]\n II.Handle suffix\n  ResearchRegex@   (?:\\))(?:[^\\,]*)\n  ReplaceString@   [EMPTY]\n III.Watch out whether need to clear the rare character ',' at the last line\n\n12. Cron Expression\n每隔5秒执行一次:                  */5 * * * * ?\n每隔5分钟执行一次:                0 */5 * * * ?\n每天23点执行一次:                 0 0 23 * * ?\n每天凌晨2点执行一次:               0 0 2 * * ?\n每月2号凌晨4点执行一次：            0 0 2 4 * ?\n每月最后一天23点执行一次：          0 0 23 L * ?\n每周星期天凌晨2点实行一次：          0 0 2 ? * L\n在26分、29分、33分执行一次：        0 26,29,33 * * * ?\n每天的0点、22点、23点都执行一次：    0 0 0 0,22,23 * * ?\n"
  },
  {
    "path": "src/main/resources/template/SQLTemplate.txt",
    "content": "\n-- ----------------------------\n-- D8ger-Sql-Auto-Generated\n-- Table structure for `@mo_table_name@`\n-- @author @d8Author@\n-- ----------------------------\n-- DROP TABLE IF EXISTS `@mo_table_name@`;\nCREATE TABLE `@mo_table_name@`\n(\n@sql_column@\n)\n    comment '@MoName@表' charset = utf8mb4;\n"
  },
  {
    "path": "src/main/resources/template/SwaggerMoTemplate.txt",
    "content": "package @swaggerMoPackage@;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Date;\n\n/**\n * @MoName@Mo对应的SwaggerApi增强Vo对象\n *\n * @author @d8Author@\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\n@ApiModel\npublic class @MoName@Vo {\n\n@swaggerField@\n\n}"
  },
  {
    "path": "src/main/resources/template/caofan.txt",
    "content": "==== iTerm2快捷键 ====\n\n# 高亮光标位置\ncmd + /\n# 窗口弹出历史命令\ncmd + sft + h\n# 删除当前行\n^ + u\n# 跳到行首\n^ + a\n# 跳到行尾\n^ + e\n# 删除光标所在字符(向后删除)\n^ + d\n# 删除光标前一个字符(向前删除)\n^ + h <==> delete\n# 交换光标最近前两个字符\n^ + t\n# 单词向左跳跃(回去)\nEsc + b ==> 自定义关联 ^ + b\n# 单词向右跳跃(前进)\nEsc + f ==> 自定义关联 ^ + f\n\n\n==== vim快捷键 ====\n- 非INSERT预览模式 -\n# 单词向右跳跃\ne ==> 向右跳跃2个单词 2 + e\n# 单词向左跳跃\nb ==> 向左跳跃2个单词 2 + b\n# 向下移动2行\n2 + j\n# 向上移动2行\n2 + k\n# 跳到第一行行首\ngg\n# 跳到最后一行行首\nG\n# 跳到当前行行首\nO\n# 跳到当前行非空白字符行首\n^\n# 跳到当前行行尾\n$\n# 删除当前字符\nx\n# 替换当前字符(每次只能替换一个字符)\nr\n# 删除一行\ndd\n# 从当前行开始复制并粘贴2行\n2 + yy + p\n# 撤销上一次操作\nu\n# 还原上一次撤销\n^ + r\n\n\n\n==== mac OS快捷键 ====\n\n\n\n\n\n\n\n\n==== IDEA快捷键 ====\n\n\n"
  },
  {
    "path": "src/main/resources/template/d8ger-util-list.txt",
    "content": "🌟 autojump\n🌟 dart\n🌟 ffmpeg\n🌟 gource\n🌟 gradle\n🌟 httpie\n🌟 keystone\n🌟 lrzsz\n🌟 openssl\n🌟 python@3.8\n🌟 rename\n🌟 sshpass\n🌟 thefuck\n🌟 tree\n🌟 youtube🌟dl\n🌟 zsh\n\naom\nboost\ncairo\ncapstone\nflac\nfontconfig\nfreetype\nfrei0r\nfribidi\ngdbm\ngettext\ngiflib\nglew\nglib\ngmp\ngnutls\ngraphite2\nharfbuzz\nicu4c\njpeg\nlame\nleptonica\nlibass\nlibbluray\nlibevent\nlibffi\nlibidn2\nlibogg\nlibplist\nlibpng\nlibsamplerate\nlibsndfile\nlibsoxr\nlibtasn1\nlibtiff\nlibunistring\nlibvidstab\nlibvorbis\nlibvpx\nlittle-cms2\nlzo\nncurses\nnettle\nopencore-amr\nopenjpeg\nopenssl@1.1\nopus\np11-kit\npcre\npixman\npython\nrapidjson\nreadline\nrtmpdump\nrubberband\nsdl2\nsdl2_image\nsnappy\nspeex\nsqlite\ntesseract\ntesseract🌟lang\ntheora\nunbound\nwebp\nwget\nx264\nx265\nxvid\nxz\n\n"
  },
  {
    "path": "src/main/resources/template/javaShorts.txt",
    "content": "/apim : SwaggerModel字段属性模板\n\noin  : 对象为null         ==> Objects.isNull()\nonn  : 对象不为null       ==> Objects.nonNull()\no2e  : 两对象相等         ==> Objects.equals(, )\none  : 两对象不相等       ==> !Objects.equals(, )\nfoin : 判断对象为null     ==> if (Objects.isNull()) {}\nfonn : 判断对象不为null   ==> if (Objects.nonNull()) {}\nfo2e : 判断两对象相等     ==> if (Objects.equals(, )) {}\nfone : 判断两对象不相等   ==> if (!Objects.equals(, )) {}\n\ncie  : 集合为空           ==> CollectionUtil.isEmpty()\ncne  : 集合不为空         ==> CollectionUtil.isNotEmpty()\nsib  : 字符串为空         ==> StringUtils.isBlank()\nsnb  : 字符串不为空       ==> StringUtils.isNotBlank()\nfcie : 判断集合为空       ==> if (CollectionUtil.isEmpty()){}\nfcne : 判断集合不为空     ==> if (CollectionUtil.isNotEmpty()){}\nfsib : 判断字符串为空     ==> if (StringUtils.isBlank()) {}\nfsnb : 判断字符串不为空   ==> if (StringUtils.isNotBlank()) {}\n"
  },
  {
    "path": "src/main/resources/template/normal.command",
    "content": "# mvn编译检查详细未检查异常信息\nmcf compile -Xlint:unchecked\n\nhttp --verify=no -v -f POST https://1.d8ger.com/uploadFile param1:=1 file@~/tmpUploadFile/xxx.png\n\n# 使用chrome的插件下载cookies.txt\nyoutube-dl --cookies cookies.txt  --proxy http://127.0.0.1:1087/ -F  网址\nyoutube-dl --cookies cookies.txt  --proxy http://127.0.0.1:1087/ https://www.youtube.com/watch\\?v\\=Y4WgD0FljKU   -x --audio-format mp3\n\n# AsciiDoc转markdown\nbrew install asciidoc\nbrew install pandoc\nasciidoc -b docbook acm.adoc\niconv -t utf-8 acm.xml | pandoc -f docbook -t markdown_strict --wrap=none | iconv -f utf-8 > acm.md\n"
  },
  {
    "path": "src/main/resources/template/ohmyd8ger.command",
    "content": "alias searchPID='searchPID'\nalias killPID='killPID'\nalias searchPortOccupy='searchPortOccupy'\nalias https-downLoadResponse='downLoadResponse'\nalias 'showssh=ps -ef | grep ssh'\nalias https-show='show'\nalias https-downLoadExcel='downLoadExcel'\nalias https-downloadD8ger='downloadD8ger'\n\nalias 'xDev=xDev'\nalias 'xDevNormal=xDevNormal'\nalias 'xDevSSO=xDevSSO'\nalias 'refreshDevAccount=refreshDevAccount'\n\nalias 'rh=reportHelp'\nalias 'logo=logo'\nalias 'hison=history | grep \"https.*willclass\\.com\" | tail -n 8'\nalias 'tsm=teacherChangeSchool'\n\nalias 'ip=ifconfig | grep 172'\nalias 'arthas-start=java -jar /Users/D8GER/Desktop/CAOFAN/Arthas/arthas-boot.jar'\n\nalias 'jsh=cat ~/javaShorts.txt'\nalias 'fkgrep=cat ~/fk-grep.d8ger'\nalias 'dev=cat ~/DEV.properties'\nalias 'devShow=cat ~/dev.yml'\nalias 'phelp=cat ~/pad.command'\nalias 'chelp=cat ~/normal.command'\nalias 'arthasHelp=cat ~/althas-help.command'\nalias 'logSH=cat ~/project-log-help.command'\n\n"
  },
  {
    "path": "src/test/java/d8ger/D8T.java",
    "content": "package d8ger;\n\nimport org.junit.Test;\n\n/**\n * This is a Test Demo showing how to execute a test case by junit.\n *\n * @author D8GER\n */\npublic class D8T {\n\n\n    @Test\n    public void hello() {\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/resources/MyJSON.txt",
    "content": ""
  }
]