YashanDB兼容Flowable6.8.0

一、背景描述

最近有一个系统需要做信创改造,旧项目系统使用mysql存储业务数据,计划切换到国产数据库。业务项目使用flowable6.8.0 工作流框架,需要动手做兼容适配。
本篇文章讲解如何通过修改少量源代码,完成Flowable6.8.0框架适配一款国产数据库(Yashandb)。

二、Flowable框架简介

较早的⼯作流是 jBPM , 这是⼀个由 Java 实现的企业级流程引擎,是 JBoss 公司开发的产品之⼀ 。 jBPM 的创建者是 Tom Baeyens , 这个⼤佬后来离开了 JBoss , 并加⼊到 Alfresco , 并推出了基于 jBPM4 的开源工作流系统 Activiti , 而jBPM 则在 后续的代码中完全放弃了 jBPM4 的代码 。在jBPM 在发展过程中 , 由于意见相左 , 后来变成了两个 jBPM 和 Activiti 。然⽽戏剧的是 , Activiti5 没搞多久 , 从 Activiti 中⼜分出来⼀个 Camunda , Activiti 继续发展 , ⼜从中分出来⼀个 Flowable。
市面上,主流的流程引擎共有三个:Activiti 、Flowable 和Camunda。

  1. Activiti 目前是侧重云, 它⽬前的设计会向 Spring Cloud、Docker 靠拢 。
  2. Flowable 核心思想还是在做⼀个功能丰富的流程引擎⼯具, 除了最基础的⼯作流, 它还提供许多其他的扩展点 , 我们可以基于Flowable 实现出许多我们想要的功能 。
  3. Camunda 相对于前两个而言比较轻量级 , Camunda 有⼀个比较有特⾊的功能就是他提 供了⼀个小巧的编辑器 , 基于 bpmn.io](http://bpmn.io)) 来实现的 。如果你的项⽬需求是做⼀个轻巧的、灵活的、定制性强的编辑器 , ⼯作流是嵌⼊式的,那么可以选择 Camunda 。

三、框架适配详细描述

3.1 添加maven依赖

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/>
    </parent>

    <properties>
        <flowable.version>6.8.0</flowable.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter-test</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <!--    springboot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.yashandb</groupId>
            <artifactId>yashandb-jdbc</artifactId>
            <version>1.6.1</version>
        </dependency>n

        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter</artifactId>
            <version>${flowable.version}</version>
 
        </dependency>


 


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>

         

    </dependencies>

3.2 application.yml 添加依赖项

spring:
  datasource:
#    url: jdbc:yasdb://192.168.33.103:6688/yasdb
    url: jdbc:yasdb://192.168.33.103:3688/yasdb
    username: flowable
    password: flowable
    driver-class-name: com.yashandb.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
#  liquibase:
#
#    enabled: true
#    drop-first: true
flowable:
  #关闭定时任务JOB
  async-executor-activate: true
  database-schema-update: true
#  database-schema: flowable



server:
  port: 8081


3.3 添加适配代码

3.3.1 liquibase 代码重构

3.3.1.1 重写AbstractJdbcDatabase

重写AbstractJdbcDatabase,增加Yashandb数据库
新建package(liquibase.database.core)–>新建YASDatabase.java并继承AbstractJdbcDatabase抽象 类–>将具体的类实现从OracleDatabase类复制进去(liquibase-core-4.9.1.jar包的liquibase.database.core路径)
YASDatabase.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package liquibase.database.core;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import liquibase.CatalogAndSchema;
import liquibase.Scope;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.DatabaseConnection;
import liquibase.database.OfflineConnection;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.exception.ValidationErrors;
import liquibase.executor.ExecutorService;
import liquibase.statement.DatabaseFunction;
import liquibase.statement.SequenceCurrentValueFunction;
import liquibase.statement.SequenceNextValueFunction;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.RawCallStatement;
import liquibase.statement.core.RawSqlStatement;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Catalog;
import liquibase.structure.core.Index;
import liquibase.structure.core.PrimaryKey;
import liquibase.structure.core.Schema;
import liquibase.util.JdbcUtils;
import liquibase.util.StringUtil;

public class YASDatabase extends AbstractJdbcDatabase {
//    YASDB配置项
    private static final String PRODUCT_NAME = "YashanDB";
    private static final String PRODUCT_SHORT_NAME = "YasDB";
    private static final String DEFAULT_DRIVER = "com.yashandb.jdbc.Driver";
    private static final Integer DEFAULT_PORT = 1688;


    @Override
    protected String getDefaultDatabaseProductName() {
        return PRODUCT_NAME;
    }

    /**
     * Is this AbstractDatabase subclass the correct one to use for the given connection.
     *
     * @param conn
     */
    @Override
    public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
//        return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
        return  (
                (PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName()))
                        || (PRODUCT_SHORT_NAME.equalsIgnoreCase(conn.getDatabaseProductName()))
        );
    }


    /**
     * If this database understands the given url, return the default driver class name.  Otherwise return null.
     *
     * @param url
     */
    @Override
    public String getDefaultDriver(String url) {
        if(url.startsWith("jdbc:yasdb")) {
            return DEFAULT_DRIVER;
        }

        return null;
    }

    /**
     * Returns an all-lower-case short name of the product.  Used for end-user selecting of database type
     * such as the DBMS precondition.
     */
    @Override
    public String getShortName() {
        return PRODUCT_SHORT_NAME;

    }

    @Override
    public Integer getDefaultPort() {
        return DEFAULT_PORT;
    }

    /**
     * Returns whether this database support initially deferrable columns.
     */
    @Override
    public boolean supportsInitiallyDeferrableColumns() {
        return false;
    }

    @Override
    public boolean supportsTablespaces() {
        return true;
    }

    @Override
    public int getPriority() {
        return PRIORITY_DEFAULT;
    }


    private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*");

    protected final int SHORT_IDENTIFIERS_LENGTH = 30;
    protected final int LONG_IDENTIFIERS_LEGNTH = 128;
    public static final int ORACLE_12C_MAJOR_VERSION = 12;

    private Set<String> reservedWords = new HashSet<>();
    private Set<String> userDefinedTypes;
    private Map<String, String> savedSessionNlsSettings;

    private Boolean canAccessDbaRecycleBin;
    private Integer databaseMajorVersion;
    private Integer databaseMinorVersion;



    /**
     * Default constructor for an object that represents the Oracle Database DBMS.
     */
    public YASDatabase() {
        super.unquotedObjectsAreUppercased = true;
        //noinspection HardCodedStringLiteral
        super.setCurrentDateTimeFunction("SYSTIMESTAMP");
        // Setting list of Oracle's native functions
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("SYSDATE"));
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));
        //noinspection HardCodedStringLiteral
        super.sequenceNextValueFunction = "%s.nextval";
        //noinspection HardCodedStringLiteral
        super.sequenceCurrentValueFunction = "%s.currval";
    }

    private void tryProxySession(final String url, final Connection con) {
        Matcher m = PROXY_USER.matcher(url);
        if (m.matches()) {
            Properties props = new Properties();
            props.put("PROXY_USER_NAME", m.group(1));
            try {
                Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class);
                method.setAccessible(true);
                method.invoke(con, 1, props);
            } catch (Exception e) {
                Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage());
            }
        }
    }

    @Override
    public int getDatabaseMajorVersion() throws DatabaseException {
        if (databaseMajorVersion == null) {
            return super.getDatabaseMajorVersion();
        } else {
            return databaseMajorVersion;
        }
    }

    @Override
    public int getDatabaseMinorVersion() throws DatabaseException {
        if (databaseMinorVersion == null) {
            return super.getDatabaseMinorVersion();
        } else {
            return databaseMinorVersion;
        }
    }

    @Override
    public String getJdbcCatalogName(CatalogAndSchema schema) {
        return null;
    }

    @Override
    public String getJdbcSchemaName(CatalogAndSchema schema) {
        return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);
    }

    @Override
    protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) {
        if (StringUtil.isEmpty(generationType)) {
            return super.getAutoIncrementClause();
        }

        String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ]
        String generationStrategy = generationType;
        if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {
            generationStrategy += " ON NULL";
        }
        return String.format(autoIncrementClause, generationStrategy);
    }

    @Override
    public String generatePrimaryKeyName(String tableName) {
        if (tableName.length() > 27) {
            //noinspection HardCodedStringLiteral
            return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27);
        } else {
            //noinspection HardCodedStringLiteral
            return "PK_" + tableName.toUpperCase(Locale.US);
        }
    }

    @Override
    public boolean isReservedWord(String objectName) {
        return reservedWords.contains(objectName.toUpperCase());
    }

    @Override
    public boolean supportsSequences() {
        return true;
    }

    /**
     * Oracle supports catalogs in liquibase terms
     *
     * @return false
     */
    @Override
    public boolean supportsSchemas() {
        return false;
    }

    @Override
    protected String getConnectionCatalogName() throws DatabaseException {
        if (getConnection() instanceof OfflineConnection) {
            return getConnection().getCatalog();
        }
        try {
            //noinspection HardCodedStringLiteral
            return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);
        } catch (Exception e) {
            //noinspection HardCodedStringLiteral
            Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e);
        }
        return null;
    }

    @Override
    public String getDefaultCatalogName() {//NOPMD
        return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);
    }

    /**
     * <p>Returns an Oracle date literal with the same value as a string formatted using ISO 8601.</p>
     *
     * <p>Convert an ISO8601 date string to one of the following results:
     * to_date('1995-05-23', 'YYYY-MM-DD')
     * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')</p>
     * <p>
     * Implementation restriction:<br>
     * Currently, only the following subsets of ISO8601 are supported:<br>
     * <ul>
     * <li>YYYY-MM-DD</li>
     * <li>YYYY-MM-DDThh:mm:ss</li>
     * </ul>
     */
    @Override
    public String getDateLiteral(String isoDate) {
        String normalLiteral = super.getDateLiteral(isoDate);

        if (isDateOnly(isoDate)) {
            return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')";
        } else if (isTimeOnly(isoDate)) {
            return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')";
        } else if (isTimestamp(isoDate)) {
            return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')";
        } else if (isDateTime(isoDate)) {
            int seppos = normalLiteral.lastIndexOf('.');
            if (seppos != -1) {
                normalLiteral = normalLiteral.substring(0, seppos) + "'";
            }
            return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')";
        }
        return "UNSUPPORTED:" + isoDate;
    }

    @Override
    public boolean isSystemObject(DatabaseObject example) {
        if (example == null) {
            return false;
        }

        if (this.isLiquibaseObject(example)) {
            return false;
        }

        if (example instanceof Schema) {
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) {
                return true;
            }
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) {
                return true;
            }
        } else if (isSystemObject(example.getSchema())) {
            return true;
        }
        if (example instanceof Catalog) {
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) {
                return true;
            }
        } else if (example.getName() != null) {
            //noinspection HardCodedStringLiteral
            if (example.getName().startsWith("BIN$")) { //oracle deleted table
                boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin();
                if (!filteredInOriginalQuery) {
                    filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName());
                }

                if (filteredInOriginalQuery) {
                    return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof
                            liquibase.statement.UniqueConstraint));
                } else {
                    return true;
                }
            } else //noinspection HardCodedStringLiteral
                if (example.getName().startsWith("AQ$")) { //oracle AQ tables
                    return true;
                } else //noinspection HardCodedStringLiteral
                    if (example.getName().startsWith("DR$")) { //oracle index tables
                        return true;
                    } else //noinspection HardCodedStringLiteral
                        if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table
                            return true;
                        } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral
                            if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) {
                                // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed.
                                return true;
                            } else //noinspection HardCodedStringLiteral
                                if (example.getName().startsWith("MLOG$_")) { //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations.
                                    return true;
                                } else //noinspection HardCodedStringLiteral
                                    if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations.
                                        return true;
                                    } else //noinspection HardCodedStringLiteral
                                        if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables.
                                            return true;
                                        } else //noinspection HardCodedStringLiteral
                                            if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) { //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object.
                                                return true;
                                            } else //noinspection HardCodedStringLiteral
                                                if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema.
                                                    return true;
                                                } else //noinspection HardCodedStringLiteral
                                                    if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence
                                                        return true;
                                                    } else //noinspection HardCodedStringLiteral
                                                        if (example.getName().startsWith("USLOG$")) { //for update materialized view
                                                            return true;
                                                        } else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables
                                                            return true;
                                                        }
        }

        return super.isSystemObject(example);
    }

    @Override
    public boolean supportsAutoIncrement() {
        // Oracle supports Identity beginning with version 12c
        boolean isAutoIncrementSupported = false;

        try {
            if (getDatabaseMajorVersion() >= 12) {
                isAutoIncrementSupported = true;
            }

            // Returning true will generate create table command with 'IDENTITY' clause, example:
            // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));

            // While returning false will continue to generate create table command without 'IDENTITY' clause, example:
            // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));

        } catch (DatabaseException ex) {
            isAutoIncrementSupported = false;
        }

        return isAutoIncrementSupported;
    }


//    public Set<UniqueConstraint> findUniqueConstraints(String schema) throws DatabaseException {
//        Set<UniqueConstraint> returnSet = new HashSet<UniqueConstraint>();
//
//        List<Map> maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME"));
//
//        UniqueConstraint constraint = null;
//        for (Map map : maps) {
//            if (constraint == null || !constraint.getName().equals(constraint.getName())) {
//                returnSet.add(constraint);
//                Table table = new Table((String) map.get("TABLE_NAME"));
//                constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table);
//            }
//        }
//        if (constraint != null) {
//            returnSet.add(constraint);
//        }
//
//        return returnSet;
//    }

    @Override
    public boolean supportsRestrictForeignKeys() {
        return false;
    }

    @Override
    public int getDataTypeMaxParameters(String dataTypeName) {
        //noinspection HardCodedStringLiteral
        if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) {
            return 0;
        }
        //noinspection HardCodedStringLiteral
        if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) {
            return 0;
        }
        return super.getDataTypeMaxParameters(dataTypeName);
    }

    public String getSystemTableWhereClause(String tableNameColumn) {
        List<String> clauses = new ArrayList<String>(Arrays.asList("BIN$",
                "AQ$",
                "DR$",
                "SYS_IOT_OVER",
                "MLOG$_",
                "RUPD$_",
                "WM$_",
                "ISEQ$$_",
                "USLOG$",
                "SYS_FBA"));

        for (int i = 0;i<clauses.size(); i++) {
            clauses.set(i, tableNameColumn+" NOT LIKE '"+clauses.get(i)+"%'");
        }
        return "("+ StringUtil.join(clauses, " AND ") + ")";
    }

    @Override
    public boolean jdbcCallsCatalogsSchemas() {
        return true;
    }

    public Set<String> getUserDefinedTypes() {
        if (userDefinedTypes == null) {
            userDefinedTypes = new HashSet<>();
            if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) {
                try {
                    try {
                        //noinspection HardCodedStringLiteral
                        userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class));
                    } catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES
                        //noinspection HardCodedStringLiteral
                        userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class));
                    }
                } catch (DatabaseException e) {
                    //ignore error
                }
            }
        }

        return userDefinedTypes;
    }

    @Override
    public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) {
        //noinspection HardCodedStringLiteral
        if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) {
            return databaseFunction.toString();
        }
        if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof
                SequenceCurrentValueFunction)) {
            String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction);
            // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval
            return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\"");

        }

        return super.generateDatabaseFunctionValue(databaseFunction);
    }

    @Override
    public ValidationErrors validate() {
        ValidationErrors errors = super.validate();
        DatabaseConnection connection = getConnection();
        if ((connection == null) || (connection instanceof OfflineConnection)) {
            //noinspection HardCodedStringLiteral
            Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database");
            return errors;
        }

        if (!canAccessDbaRecycleBin()) {
            errors.addWarning(getDbaRecycleBinWarning());
        }

        return errors;

    }

    public String getDbaRecycleBinWarning() {
        //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,
        // HardCodedStringLiteral
        //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
        return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " +
                "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " +
                "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" +
                " issue.\n" +
                "\n" +
                "The user you used to connect to the database (" + getConnection().getConnectionUserName() +
                ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " +
                "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" +
                "\n" +
                "     GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";";
    }

    public boolean canAccessDbaRecycleBin() {
        if (canAccessDbaRecycleBin == null) {
            DatabaseConnection connection = getConnection();
            if ((connection == null) || (connection instanceof OfflineConnection)) {
                return false;
            }

            Statement statement = null;
            try {
                statement = ((JdbcConnection) connection).createStatement();
                @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1");
                resultSet.close(); //don't need to do anything with the result set, just make sure statement ran.
                this.canAccessDbaRecycleBin = true;
            } catch (Exception e) {
                //noinspection HardCodedStringLiteral
                if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist
                    this.canAccessDbaRecycleBin = false;
                } else {
                    //noinspection HardCodedStringLiteral
                    Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e);
                    this.canAccessDbaRecycleBin = false;
                }
            } finally {
                JdbcUtils.close(null, statement);
            }
        }

        return canAccessDbaRecycleBin;
    }

    @Override
    public boolean supportsNotNullConstraintNames() {
        return true;
    }

    /**
     * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has
     * the following form (case-insensitive comparison):
     * 1st character: A-Z
     * 2..n characters: A-Z0-9$_#
     * The maximum length of an identifier differs by Oracle version and object type.
     */
    public boolean isValidOracleIdentifier(String identifier, Class<? extends DatabaseObject> type) {
        if ((identifier == null) || (identifier.length() < 1))
            return false;

        if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$"))
            return false;

        /*
         * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes
         * we do know seem to be supported as 12cR2 long identifiers, so:
         */
        return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH);
    }

    /**
     * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this
     * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare
     * object types).
     *
     * @return the maximum length of an object identifier, in bytes
     */
    public int getIdentifierMaximumLength() {
        try {
            if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) {
                return SHORT_IDENTIFIERS_LENGTH;
            } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) {
                return SHORT_IDENTIFIERS_LENGTH;
            } else {
                return LONG_IDENTIFIERS_LEGNTH;
            }
        } catch (DatabaseException ex) {
            throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex);
        }

    }

}

3.3.1.2 重写liquibase.datatype.core.BooleanType

重写liquibase.datatype.core.BooleanType以支持将int类型与java的Boolean类型的转换
新建package(liquibase.datatype.core)–>新建java(BooleanType 并继承 LiquibaseDataType )

package liquibase.datatype.core;

import liquibase.change.core.LoadDataChange;
import liquibase.database.Database;
import liquibase.database.core.*;
import liquibase.datatype.DataTypeInfo;
import liquibase.datatype.DatabaseDataType;
import liquibase.datatype.LiquibaseDataType;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
import liquibase.statement.DatabaseFunction;
//import liquibase.util.StringUtils;

import java.util.Locale;

@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT)
public class BooleanType extends LiquibaseDataType {

    @Override
    public DatabaseDataType toDatabaseDataType(Database database) {
        String originalDefinition = StringUtils.trimToEmpty(getRawDefinition());
        if ((database instanceof Firebird3Database)) {
            return new DatabaseDataType("BOOLEAN");
        }
        if ((database instanceof AbstractDb2Database) || (database instanceof FirebirdDatabase)) {
            return new DatabaseDataType("SMALLINT");
        } else if (database instanceof MSSQLDatabase) {
            return new DatabaseDataType(database.escapeDataTypeName("bit"));
        } else if (database instanceof MySQLDatabase) {
            if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {
                return new DatabaseDataType("BIT", getParameters());
            }
            return new DatabaseDataType("BIT", 1);
        } else if (database instanceof OracleDatabase) {
            return new DatabaseDataType("NUMBER", 1);
        } else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) {
            return new DatabaseDataType("BIT");
        } else if (database instanceof DerbyDatabase) {
            if (((DerbyDatabase) database).supportsBooleanDataType()) {
                return new DatabaseDataType("BOOLEAN");
            } else {
                return new DatabaseDataType("SMALLINT");
            }
        } else if (database.getClass().isAssignableFrom(DB2Database.class)) {
            if (((DB2Database) database).supportsBooleanDataType()) {
                return new DatabaseDataType("BOOLEAN");
            } else {
                return new DatabaseDataType("SMALLINT");
            }
        } else if (database instanceof HsqlDatabase) {
            return new DatabaseDataType("BOOLEAN");
        } else if (database instanceof PostgresDatabase) {
            if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {
                return new DatabaseDataType("BIT", getParameters());
            }
        } else if (database instanceof YASDatabase){
            return new DatabaseDataType("INT");
        }

        return super.toDatabaseDataType(database);
    }

    @Override
    public String objectToSql(Object value, Database database) {
        if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) {
            return null;
        }

        String returnValue;
        if (value instanceof String) {
            value = ((String) value).replaceAll("'", "");
            if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) {
                returnValue = this.getTrueBooleanValue(database);
            } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals(
                    ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) {
                returnValue = this.getFalseBooleanValue(database);
            } else {
                throw new UnexpectedLiquibaseException("Unknown boolean value: " + value);
            }
        } else if (value instanceof Long) {
            if (Long.valueOf(1).equals(value)) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else if (value instanceof Number) {
            if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else if (value instanceof DatabaseFunction) {
            return value.toString();
        } else if (value instanceof Boolean) {
            if (((Boolean) value)) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else {
            throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value");
        }

        return returnValue;
    }

    @Override
    public Object sqlToObject(String value, Database database) {
        if (database instanceof YASDatabase){
            return "1".equalsIgnoreCase(value)? Boolean.TRUE: ("0".equalsIgnoreCase(value)?Boolean.FALSE:Boolean.FALSE);
        }
        return super.sqlToObject(value, database);
    }

    protected boolean isNumericBoolean(Database database) {
        if (database instanceof DerbyDatabase) {
            return !((DerbyDatabase) database).supportsBooleanDataType();
        } else if (database.getClass().isAssignableFrom(DB2Database.class)) {
            return !((DB2Database) database).supportsBooleanDataType();
//        } else if (database instanceof YASDatabase){
//            return !((YASDatabase) database).supportsBooleanDataType();
        }
        return (database instanceof Db2zDatabase) || (database instanceof DB2Database) || (database instanceof FirebirdDatabase) || (database instanceof
                MSSQLDatabase) || (database instanceof MySQLDatabase) || (database instanceof OracleDatabase) ||
                (database instanceof SQLiteDatabase) || (database instanceof SybaseASADatabase) || (database instanceof
                SybaseDatabase);
    }

    /**
     * The database-specific value to use for "false" "boolean" columns.
     */
    public String getFalseBooleanValue(Database database) {
        if (isNumericBoolean(database)) {
            return "0";
        }
        if (database instanceof InformixDatabase) {
            return "'f'";
        }
        return "FALSE";
    }

    /**
     * The database-specific value to use for "true" "boolean" columns.
     */
    public String getTrueBooleanValue(Database database) {
        if (isNumericBoolean(database)) {
            return "1";
        }
        if (database instanceof InformixDatabase) {
            return "'t'";
        }
        return "TRUE";
    }

    @Override
    public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {
        return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN;
    }

}

3.3.1.3 新建DateTimeType.java,处理liquibase框架的日期类型

新建package(liquibase.datatype.core)–>新建DateTimeType.java

package liquibase.datatype.core;

import liquibase.change.core.LoadDataChange;
import liquibase.database.Database;
import liquibase.database.core.*;
import liquibase.datatype.DataTypeInfo;
import liquibase.datatype.DatabaseDataType;
import liquibase.datatype.LiquibaseDataType;
import liquibase.logging.LogService;
//import liquibase.logging.LogType;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
import liquibase.statement.DatabaseFunction;
//import liquibase.util.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;

@DataTypeInfo(name = "datetime", minParameters = 0, maxParameters = 1,
        aliases = {"java.sql.Types.DATETIME", "java.util.Date", "smalldatetime", "datetime2", "datetime"},
        priority = LiquibaseDataType.PRIORITY_DEFAULT)
public class DateTimeType extends LiquibaseDataType {

    protected static final String SQL_DATETYPE_TIMESTAMP = "TIMESTAMP";

    @Override
    public DatabaseDataType toDatabaseDataType(Database database) {
        if ((database instanceof DerbyDatabase) || (database instanceof FirebirdDatabase) || (database instanceof
                H2Database) || (database instanceof HsqlDatabase)) {
            return new DatabaseDataType(SQL_DATETYPE_TIMESTAMP);
        }

        if (database instanceof AbstractDb2Database) {
            return new DatabaseDataType(SQL_DATETYPE_TIMESTAMP, getParameters());
        }

        if (database instanceof OracleDatabase) {
            if (getRawDefinition().toUpperCase(Locale.US).contains("TIME ZONE")) {
                // remove the last data type size that comes from column size
                return new DatabaseDataType(getRawDefinition().replaceFirst("\\(\\d+\\)$", ""));
            }
            return new DatabaseDataType(SQL_DATETYPE_TIMESTAMP, getParameters());
        }

        String originalDefinition = StringUtils.trimToEmpty(getRawDefinition());
        if (database instanceof MSSQLDatabase) {
            Object[] parameters = getParameters();
            if (originalDefinition.matches("(?i)^\\[?smalldatetime.*")) {
                return new DatabaseDataType(database.escapeDataTypeName("smalldatetime"));
            } else if ("datetime2".equals(originalDefinition.toLowerCase(Locale.US))
                    || "[datetime2]".equals(originalDefinition.toLowerCase(Locale.US))
                    || originalDefinition.toLowerCase(Locale.US).matches("(?i)\\[?datetime2\\]?\\s*\\(.+")
            ) {

                // If the scale for datetime2 is the database default anyway, omit it.
                if ( (parameters.length >= 1) &&
                        (Integer.parseInt(parameters[0].toString())
                                == (database.getDefaultScaleForNativeDataType("datetime2"))) ) {
                    parameters = new Object[0];
                }
                return new DatabaseDataType(database.escapeDataTypeName("datetime2"), parameters);
            }
            return new DatabaseDataType(database.escapeDataTypeName("datetime"));
        }
        if (database instanceof InformixDatabase) {

            // From database to changelog
            if (((getAdditionalInformation() == null) || getAdditionalInformation().isEmpty())
                    && ((getParameters() != null) && (getParameters().length > 0))) {

                String parameter = String.valueOf(getParameters()[0]);

                if ("4365".equals(parameter)) {
                    return new DatabaseDataType("DATETIME YEAR TO FRACTION(3)");
                }

                if ("3594".equals(parameter)) {
                    return new DatabaseDataType("DATETIME YEAR TO SECOND");
                }

                if ("3080".equals(parameter)) {
                    return new DatabaseDataType("DATETIME YEAR TO MINUTE");
                }

                if ("2052".equals(parameter)) {
                    return new DatabaseDataType("DATETIME YEAR TO DAY");
                }
            }

            // From changelog to the database
            if ((getAdditionalInformation() != null) && !getAdditionalInformation().isEmpty()) {
                return new DatabaseDataType(originalDefinition);
            }

            return new DatabaseDataType("DATETIME YEAR TO FRACTION", 5);
        }
        if (database instanceof PostgresDatabase) {
            String rawDefinition = originalDefinition.toLowerCase(Locale.US);
            Object[] params = getParameters();
            if (rawDefinition.contains("tz") || rawDefinition.contains("with time zone")) {
                if (params.length == 0 ) {
                    return new DatabaseDataType("TIMESTAMP WITH TIME ZONE");
                } else {
                    Object param = params[0];
                    if (params.length == 2) {
                        param = params[1];
                    }
                    return new DatabaseDataType("TIMESTAMP(" + param + ") WITH TIME ZONE");
                }
            } else {
                if (params.length == 0 ) {
                    return new DatabaseDataType("TIMESTAMP WITHOUT TIME ZONE");
                } else {
                    Object param = params[0];
                    if (params.length == 2) {
                        param = params[1];
                    }
                    return new DatabaseDataType("TIMESTAMP(" + param + ") WITHOUT TIME ZONE");
                }
            }
        }
        if (database instanceof SQLiteDatabase) {
            return new DatabaseDataType("TEXT");
        }

        int maxFractionalDigits = database.getMaxFractionalDigitsForTimestamp();
        if (database instanceof MySQLDatabase) {
            if ((getParameters().length == 0) || (maxFractionalDigits == 0)) {
                // fast out...
                return new DatabaseDataType(getName());
            }

            Object[] params = getParameters();
            Integer precision = Integer.valueOf(params[0].toString());
            if (precision > 6) {
//                LogService.getLog(getClass()).warning(
//                        LogType.LOG, "MySQL does not support a timestamp precision"
//                                + " of '" + precision + "' - resetting to"
//                                + " the maximum of '6'");
                params = new Object[] {6};
            }
            return new DatabaseDataType(getName(), params);
        }

        if(database instanceof YASDatabase){
            return new DatabaseDataType(SQL_DATETYPE_TIMESTAMP, getParameters());
        }

        return new DatabaseDataType(getName());
    }

    @Override
    public String objectToSql(Object value, Database database) {
        if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) {
            return null;
        } else if (value instanceof DatabaseFunction) {
            return database.generateDatabaseFunctionValue((DatabaseFunction) value);
        } else if (database.isFunction(value.toString())) {
            return value.toString();
        } else if (value instanceof String) {
            return "'" + ((String) value).replaceAll("'", "''") + "'";
        }
        return database.getDateTimeLiteral(((Timestamp) value));
    }

    @Override
    public Object sqlToObject(String value, Database database) {
        if (zeroTime(value)) {
            return value;
        }

        if (database instanceof AbstractDb2Database) {
            return value.replaceFirst("^\"SYSIBM\".\"TIMESTAMP\"\\('", "").replaceFirst("'\\)", "");
        }
        if (database instanceof DerbyDatabase) {
            return value.replaceFirst("^TIMESTAMP\\('", "").replaceFirst("'\\)", "");
        }

        try {
            DateFormat dateTimeFormat = getDateTimeFormat(database);

            if ((database instanceof OracleDatabase) && value.matches("to_date\\('\\d+\\-\\d+\\-\\d+ \\d+:\\d+:\\d+'," +
                    " 'YYYY\\-MM\\-DD HH24:MI:SS'\\)")) {
                dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:s");
                value = value.replaceFirst(".*?'", "").replaceFirst("',.*","");
            }

            if ((database instanceof HsqlDatabase) && value.matches("TIMESTAMP'\\d+\\-\\d+\\-\\d+ \\d+:\\d+:\\d+(?:\\" +
                    ".\\d+)?'")) {
                dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:s.S");
                value = value.replaceFirst(".*?'", "").replaceFirst("',.*","");
            }

            return new Timestamp(dateTimeFormat.parse(value).getTime());
        } catch (ParseException e) {
            String[] genericFormats = new String[] {"yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss" };

            //regexp can't handle millisenconds beyond three digits
            String shortenedValue = value.replaceFirst("(\\.\\d{3})\\d+", "$1");

            for (String format : genericFormats) {
                try {
                    return new Timestamp(new SimpleDateFormat(format).parse(shortenedValue).getTime());
                } catch (ParseException ignore) {
                    //doesn't match
                }
            }

            if (value.contains("/") || value.contains("-")) { //maybe a custom format the database expects. Just return it.
                return value;
            }

            return new DatabaseFunction(value);
        }
    }

    @Override
    public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {
        return LoadDataChange.LOAD_DATA_TYPE.DATE;
    }

    private boolean zeroTime(String stringVal) {
        return "".equals(stringVal.replace("-", "").replace(":", "").replace(" ", "").replace("0", ""));
    }

    protected DateFormat getDateTimeFormat(Database database) {
        if (database instanceof MySQLDatabase) {
            // TODO: Potential error, MySQL 5.6.4+ supports up to 9 fractional digits
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
        if (database instanceof MSSQLDatabase) {
            // TODO: Potential error, MSSQL supports up to 9 fractional digits
            return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        }

        if (database instanceof AbstractDb2Database) {
            return new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS");
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    }

    @Override
    public String getName() {
        return SQL_DATETYPE_TIMESTAMP;
    }
}

3.3.1.4 新建 liquibase.database.Database 文件

新增liquibase.database.Database文件,并添加Yashandb数据库

liquibase.database.core.CockroachDatabase
liquibase.database.core.DB2Database
liquibase.database.core.Db2zDatabase
liquibase.database.core.DerbyDatabase
liquibase.database.core.EnterpriseDBDatabase
liquibase.database.core.Firebird3Database
liquibase.database.core.FirebirdDatabase
liquibase.database.core.H2Database
liquibase.database.core.HsqlDatabase
liquibase.database.core.InformixDatabase
liquibase.database.core.Ingres9Database
liquibase.database.core.MSSQLDatabase
liquibase.database.core.MariaDBDatabase
liquibase.database.core.MockDatabase
liquibase.database.core.MySQLDatabase
liquibase.database.core.OracleDatabase
liquibase.database.core.PostgresDatabase
liquibase.database.core.SQLiteDatabase
liquibase.database.core.SybaseASADatabase
liquibase.database.core.SybaseDatabase
liquibase.database.core.YASDatabase
liquibase.database.core.UnsupportedDatabase

3.3.2 flowable 代码重构

3.3.2.1 重写 DmnDbSchemaManager

通过重写DmnDbSchemaManger, 改变flowable下发SQL
新建package(org.flowable.dmn.engine.impl.db) --> 新建DmnDbSchemaManager.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.flowable.dmn.engine.impl.db;

import org.flowable.common.engine.impl.db.EngineDatabaseConfiguration;
import org.flowable.common.engine.impl.db.LiquibaseBasedSchemaManager;
import org.flowable.common.engine.impl.db.LiquibaseDatabaseConfiguration;
import org.flowable.common.engine.impl.db.SchemaManager;
import org.flowable.dmn.engine.DmnEngineConfiguration;
import org.flowable.dmn.engine.impl.util.CommandContextUtil;

public class DmnDbSchemaManager extends LiquibaseBasedSchemaManager {
//    public static final String LIQUIBASE_CHANGELOG="classpath:org/flowable/dmn/db/liquibase/flowable-cus-dmn-db-changelog.xml";
      public static final String LIQUIBASE_CHANGELOG="org/flowable/dmn/db/liquibase/flowable-cus-dmn-db-changelog.xml";

    public DmnDbSchemaManager() {
//        super("dmn", LIQUIBASE_CHANGELOG, "ACT_DMN_");`
        super("dmn", LIQUIBASE_CHANGELOG, DmnEngineConfiguration.LIQUIBASE_CHANGELOG_PREFIX);
    }

    protected LiquibaseDatabaseConfiguration getDatabaseConfiguration() {
        return new EngineDatabaseConfiguration(CommandContextUtil.getDmnEngineConfiguration());
    }

    public void initSchema() {
        this.initSchema(CommandContextUtil.getDmnEngineConfiguration().getDatabaseSchemaUpdate());
    }

    public void schemaCreate() {
        this.getCommonSchemaManager().schemaCreate();
        super.schemaCreate();
    }

    public void schemaDrop() {
        try {
            super.schemaDrop();
        } catch (Exception var3) {
            this.logger.info("Error dropping dmn engine tables", var3);
        }

        try {
            this.getCommonSchemaManager().schemaDrop();
        } catch (Exception var2) {
            this.logger.info("Error dropping common tables", var2);
        }

    }

    public String schemaUpdate() {
        this.getCommonSchemaManager().schemaUpdate();
        return super.schemaUpdate();
    }

    protected SchemaManager getCommonSchemaManager() {
        return CommandContextUtil.getDmnEngineConfiguration().getCommonSchemaManager();
    }
}

3.3.2.2 增加 flowable-cus-dmn-db-changelog.xml

增加Yashandb数据库时,liquibase数据库处理行为
在resources目录下,新建package(org.flowable.dmn.db.liquibase)–>新建 flowable-cus-dmn-db-changelog.xml

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

    <changeSet id="1" author="activiti">

        <createTable tableName="ACT_DMN_DEPLOYMENT">
            <column name="ID_" type="varchar(255)">
                <constraints primaryKey="true" nullable="false" />
            </column>
            <column name="NAME_" type="varchar(255)" />
            <column name="CATEGORY_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="DEPLOY_TIME_" type="datetime">
                <constraints nullable="true" />
            </column>
            <column name="TENANT_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="PARENT_DEPLOYMENT_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
        </createTable>

        <createTable tableName="ACT_DMN_DEPLOYMENT_RESOURCE">
            <column name="ID_" type="varchar(255)">
                <constraints primaryKey="true" nullable="false" />
            </column>
            <column name="NAME_" type="varchar(255)" />
            <column name="DEPLOYMENT_ID_" type="varchar(255)" />
            <column name="RESOURCE_BYTES_" type="longblob">
                <constraints nullable="true" />
            </column>
        </createTable>

        <createTable tableName="ACT_DMN_DECISION_TABLE">
            <column name="ID_" type="varchar(255)">
                <constraints primaryKey="true" nullable="false" />
            </column>
            <column name="NAME_" type="varchar(255)" />
            <column name="VERSION_" type="int" />
            <column name="KEY_" type="varchar(255)" />
            <column name="CATEGORY_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="DEPLOYMENT_ID_" type="varchar(255)" />
            <column name="PARENT_DEPLOYMENT_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="TENANT_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="RESOURCE_NAME_" type="varchar(255)" />
            <column name="DESCRIPTION_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
        </createTable>

    </changeSet>

    <changeSet id="2" author="flowable">

        <createTable tableName="ACT_DMN_HI_DECISION_EXECUTION">
            <column name="ID_" type="varchar(255)">
                <constraints primaryKey="true" nullable="false" />
            </column>
            <column name="DECISION_DEFINITION_ID_" type="varchar(255)" />
            <column name="DEPLOYMENT_ID_" type="varchar(255)" />
            <column name="START_TIME_" type="datetime" />
            <column name="END_TIME_" type="datetime">
                <constraints nullable="true" />
            </column>
            <column name="INSTANCE_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="EXECUTION_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="ACTIVITY_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="FAILED_" type="boolean" defaultValueBoolean="false" />
            <column name="TENANT_ID_" type="varchar(255)">
                <constraints nullable="true" />
            </column>
            <column name="EXECUTION_JSON_" type="longtext">
                <constraints nullable="true" />
            </column>
        </createTable>

    </changeSet>

    <changeSet id="3" author="flowable">

        <addColumn tableName="ACT_DMN_HI_DECISION_EXECUTION">
            <column name="SCOPE_TYPE_" type="varchar(255)" />
        </addColumn>

    </changeSet>

    <changeSet id="4" author="flowable">

        <dropColumn columnName="PARENT_DEPLOYMENT_ID_" tableName="ACT_DMN_DECISION_TABLE" />

    </changeSet>

    <changeSet id="5" author="flowable" dbms="mysql,mariadb">

        <modifyDataType tableName="ACT_DMN_DEPLOYMENT" columnName="DEPLOY_TIME_" newDataType="datetime(3)" />
        <modifyDataType tableName="ACT_DMN_HI_DECISION_EXECUTION" columnName="START_TIME_" newDataType="datetime(3)" />
        <modifyDataType tableName="ACT_DMN_HI_DECISION_EXECUTION" columnName="END_TIME_" newDataType="datetime(3)" />

    </changeSet>

    <changeSet id="6" author="flowable">

        <createIndex tableName="ACT_DMN_DECISION_TABLE" indexName="ACT_IDX_DEC_TBL_UNIQ" unique="true">
            <column name="KEY_" />
            <column name="VERSION_" />
            <column name="TENANT_ID_" />
        </createIndex>

    </changeSet>
    <changeSet id="7" author="flowable" dbms="!Yashandb">

        <dropIndex tableName="ACT_DMN_DECISION_TABLE" indexName="ACT_IDX_DEC_TBL_UNIQ"/>

        <renameTable
                newTableName="ACT_DMN_DECISION"
                oldTableName="ACT_DMN_DECISION_TABLE"/>

        <createIndex tableName="ACT_DMN_DECISION" indexName="ACT_IDX_DMN_DEC_UNIQ" unique="true">
            <column name="KEY_" />
            <column name="VERSION_" />
            <column name="TENANT_ID_" />
        </createIndex>

    </changeSet>

    <changeSet id="7" author="flowable" dbms="Yashandb">
        <dropIndex tableName="ACT_DMN_DECISION_TABLE" indexName="ACT_IDX_DEC_TBL_UNIQ"/>
        <sql>
            CREATE TABLE ACT_DMN_DECISION AS SELECT * FROM ACT_DMN_DECISION_TABLE;
        </sql>
        <sql>
            DROP TABLE ACT_DMN_DECISION_TABLE;
        </sql>
        <createIndex tableName="ACT_DMN_DECISION" indexName="ACT_IDX_DMN_DEC_UNIQ" unique="true">
            <column name="KEY_" />
            <column name="VERSION_" />
            <column name="TENANT_ID_" />
        </createIndex>
    </changeSet>


    <changeSet id="8" author="flowable">

        <addColumn tableName="ACT_DMN_DECISION">
            <column name="DECISION_TYPE_" type="varchar(255)" />
        </addColumn>

    </changeSet>

    <changeSet id="9" author="flowable">

        <createIndex tableName="ACT_DMN_HI_DECISION_EXECUTION" indexName="ACT_IDX_DMN_INSTANCE_ID">
            <column name="INSTANCE_ID_" />
        </createIndex>

    </changeSet>

</databaseChangeLog>

3.3.2.3 重写 AbstractEngineConfiguration

重写AbstractEngineConfiguration,增加Yashandb产品名称
新建package(org.flowable.common.engine.impl)–>新建AbstractEngineConfiguration.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.flowable.common.engine.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.Map.Entry;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import org.apache.ibatis.type.ArrayTypeHandler;
import org.apache.ibatis.type.BigDecimalTypeHandler;
import org.apache.ibatis.type.BlobInputStreamTypeHandler;
import org.apache.ibatis.type.BlobTypeHandler;
import org.apache.ibatis.type.BooleanTypeHandler;
import org.apache.ibatis.type.ByteTypeHandler;
import org.apache.ibatis.type.ClobTypeHandler;
import org.apache.ibatis.type.DateOnlyTypeHandler;
import org.apache.ibatis.type.DateTypeHandler;
import org.apache.ibatis.type.DoubleTypeHandler;
import org.apache.ibatis.type.FloatTypeHandler;
import org.apache.ibatis.type.IntegerTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.LongTypeHandler;
import org.apache.ibatis.type.NClobTypeHandler;
import org.apache.ibatis.type.NStringTypeHandler;
import org.apache.ibatis.type.ShortTypeHandler;
import org.apache.ibatis.type.SqlxmlTypeHandler;
import org.apache.ibatis.type.StringTypeHandler;
import org.apache.ibatis.type.TimeOnlyTypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.api.engine.EngineLifecycleListener;
import org.flowable.common.engine.impl.agenda.AgendaOperationRunner;
import org.flowable.common.engine.impl.cfg.CommandExecutorImpl;
import org.flowable.common.engine.impl.cfg.IdGenerator;
import org.flowable.common.engine.impl.cfg.TransactionContextFactory;
import org.flowable.common.engine.impl.cfg.standalone.StandaloneMybatisTransactionContextFactory;
import org.flowable.common.engine.impl.db.CommonDbSchemaManager;
import org.flowable.common.engine.impl.db.DbSqlSessionFactory;
import org.flowable.common.engine.impl.db.LogSqlExecutionTimePlugin;
import org.flowable.common.engine.impl.db.MybatisTypeAliasConfigurator;
import org.flowable.common.engine.impl.db.MybatisTypeHandlerConfigurator;
import org.flowable.common.engine.impl.db.SchemaManager;
import org.flowable.common.engine.impl.event.EventDispatchAction;
import org.flowable.common.engine.impl.event.FlowableEventDispatcherImpl;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandConfig;
import org.flowable.common.engine.impl.interceptor.CommandContextFactory;
import org.flowable.common.engine.impl.interceptor.CommandContextInterceptor;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.common.engine.impl.interceptor.CommandInterceptor;
import org.flowable.common.engine.impl.interceptor.CrDbRetryInterceptor;
import org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker;
import org.flowable.common.engine.impl.interceptor.LogInterceptor;
import org.flowable.common.engine.impl.interceptor.SessionFactory;
import org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor;
import org.flowable.common.engine.impl.lock.LockManager;
import org.flowable.common.engine.impl.lock.LockManagerImpl;
import org.flowable.common.engine.impl.logging.LoggingListener;
import org.flowable.common.engine.impl.logging.LoggingSession;
import org.flowable.common.engine.impl.logging.LoggingSessionFactory;
import org.flowable.common.engine.impl.persistence.GenericManagerFactory;
import org.flowable.common.engine.impl.persistence.StrongUuidGenerator;
import org.flowable.common.engine.impl.persistence.cache.EntityCache;
import org.flowable.common.engine.impl.persistence.cache.EntityCacheImpl;
import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManager;
import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManagerImpl;
import org.flowable.common.engine.impl.persistence.entity.Entity;
import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManager;
import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManagerImpl;
import org.flowable.common.engine.impl.persistence.entity.TableDataManager;
import org.flowable.common.engine.impl.persistence.entity.TableDataManagerImpl;
import org.flowable.common.engine.impl.persistence.entity.data.ByteArrayDataManager;
import org.flowable.common.engine.impl.persistence.entity.data.PropertyDataManager;
import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisByteArrayDataManager;
import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager;
import org.flowable.common.engine.impl.runtime.Clock;
import org.flowable.common.engine.impl.service.CommonEngineServiceImpl;
import org.flowable.common.engine.impl.util.DefaultClockImpl;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.common.engine.impl.util.ReflectUtil;
import org.flowable.eventregistry.api.EventRegistryEventConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractEngineConfiguration {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    public static final String NO_TENANT_ID = "";
    public static final String DB_SCHEMA_UPDATE_FALSE = "false";
    public static final String DB_SCHEMA_UPDATE_CREATE = "create";
    public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";
    public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create";
    public static final String DB_SCHEMA_UPDATE_TRUE = "true";
    protected boolean forceCloseMybatisConnectionPool = true;
    protected String databaseType;
    protected String jdbcDriver = "org.h2.Driver";
    protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable";
    protected String jdbcUsername = "sa";
    protected String jdbcPassword = "";
    protected String dataSourceJndiName;
    protected int jdbcMaxActiveConnections = 16;
    protected int jdbcMaxIdleConnections = 8;
    protected int jdbcMaxCheckoutTime;
    protected int jdbcMaxWaitTime;
    protected boolean jdbcPingEnabled;
    protected String jdbcPingQuery;
    protected int jdbcPingConnectionNotUsedFor;
    protected int jdbcDefaultTransactionIsolationLevel;
    protected DataSource dataSource;
    protected SchemaManager commonSchemaManager;
    protected SchemaManager schemaManager;
    protected Command<Void> schemaManagementCmd;
    protected String databaseSchemaUpdate = "false";
    protected boolean useLockForDatabaseSchemaUpdate = false;
    protected String xmlEncoding = "UTF-8";
    protected CommandExecutor commandExecutor;
    protected Collection<? extends CommandInterceptor> defaultCommandInterceptors;
    protected CommandConfig defaultCommandConfig;
    protected CommandConfig schemaCommandConfig;
    protected CommandContextFactory commandContextFactory;
    protected CommandInterceptor commandInvoker;
    protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> {
        runnable.run();
    };
    protected List<CommandInterceptor> customPreCommandInterceptors;
    protected List<CommandInterceptor> customPostCommandInterceptors;
    protected List<CommandInterceptor> commandInterceptors;
    protected Map<String, AbstractEngineConfiguration> engineConfigurations = new HashMap();
    protected Map<String, AbstractServiceConfiguration> serviceConfigurations = new HashMap();
    protected ClassLoader classLoader;
    protected boolean useClassForNameClassLoading = true;
    protected List<EngineLifecycleListener> engineLifecycleListeners;
    protected Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers = new HashMap();
    protected boolean isDbHistoryUsed = true;
    protected DbSqlSessionFactory dbSqlSessionFactory;
    protected SqlSessionFactory sqlSessionFactory;
    protected TransactionFactory transactionFactory;
    protected TransactionContextFactory transactionContextFactory;
    protected boolean isBulkInsertEnabled = true;
    protected int maxNrOfStatementsInBulkInsert = 100;
    public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55;
    protected String mybatisMappingFile;
    protected Set<Class<?>> customMybatisMappers;
    protected Set<String> customMybatisXMLMappers;
    protected List<Interceptor> customMybatisInterceptors;
    protected Set<String> dependentEngineMyBatisXmlMappers;
    protected List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs;
    protected List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs;
    protected List<SessionFactory> customSessionFactories;
    protected Map<Class<?>, SessionFactory> sessionFactories;
    protected boolean enableEventDispatcher = true;
    protected FlowableEventDispatcher eventDispatcher;
    protected List<FlowableEventListener> eventListeners;
    protected Map<String, List<FlowableEventListener>> typedEventListeners;
    protected List<EventDispatchAction> additionalEventDispatchActions;
    protected LoggingListener loggingListener;
    protected boolean transactionsExternallyManaged;
    protected boolean usingRelationalDatabase = true;
    protected boolean usingSchemaMgmt = true;
    protected String databaseTablePrefix = "";
    protected String databaseWildcardEscapeCharacter;
    protected String databaseCatalog = "";
    protected String databaseSchema;
    protected boolean tablePrefixIsSchema;
    protected boolean alwaysLookupLatestDefinitionVersion;
    protected boolean fallbackToDefaultTenant;
    protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> {
        return "";
    };
    protected boolean enableLogSqlExecutionTime;
    protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();
    protected Duration lockPollRate = Duration.ofSeconds(10L);
    protected Duration schemaLockWaitTime = Duration.ofMinutes(5L);
    protected PropertyDataManager propertyDataManager;
    protected ByteArrayDataManager byteArrayDataManager;
    protected TableDataManager tableDataManager;
    protected PropertyEntityManager propertyEntityManager;
    protected ByteArrayEntityManager byteArrayEntityManager;
    protected List<EngineDeployer> customPreDeployers;
    protected List<EngineDeployer> customPostDeployers;
    protected List<EngineDeployer> deployers;
    protected boolean enableConfiguratorServiceLoader = true;
    protected List<EngineConfigurator> configurators;
    protected List<EngineConfigurator> allConfigurators;
    protected EngineConfigurator idmEngineConfigurator;
    protected EngineConfigurator eventRegistryConfigurator;
    public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL";
    public static final String PRODUCT_NAME_CRDB = "CockroachDB";
    public static final String DATABASE_TYPE_H2 = "h2";
    public static final String DATABASE_TYPE_HSQL = "hsql";
    public static final String DATABASE_TYPE_MYSQL = "mysql";
    public static final String DATABASE_TYPE_ORACLE = "oracle";
    public static final String DATABASE_TYPE_POSTGRES = "postgres";
    public static final String DATABASE_TYPE_MSSQL = "mssql";
    public static final String DATABASE_TYPE_YASDB = "yasdb";

    public static final String DATABASE_TYPE_DB2 = "db2";
    public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb";
    protected Map<Object, Object> beans;
    protected IdGenerator idGenerator;
    protected boolean usePrefixId;
    protected Clock clock;
    protected ObjectMapper objectMapper;
    public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000;
    public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000;
    protected int maxLengthStringVariableType = -1;

    public AbstractEngineConfiguration() {
    }

    public static Properties getDefaultDatabaseTypeMappings() {
        Properties databaseTypeMappings = new Properties();
        databaseTypeMappings.setProperty("H2", "h2");
        databaseTypeMappings.setProperty("HSQL Database Engine", "hsql");
        databaseTypeMappings.setProperty("MySQL", "mysql");
        databaseTypeMappings.setProperty("MariaDB", "mysql");
        databaseTypeMappings.setProperty("Oracle", "oracle");
        databaseTypeMappings.setProperty("PostgreSQL", "postgres");
        databaseTypeMappings.setProperty("Microsoft SQL Server", "mssql");
        databaseTypeMappings.setProperty("db2", "db2");
        databaseTypeMappings.setProperty("DB2", "db2");
        databaseTypeMappings.setProperty("DB2/NT", "db2");
        databaseTypeMappings.setProperty("DB2/NT64", "db2");
        databaseTypeMappings.setProperty("DB2 UDP", "db2");
        databaseTypeMappings.setProperty("DB2/LINUX", "db2");
        databaseTypeMappings.setProperty("DB2/LINUX390", "db2");
        databaseTypeMappings.setProperty("DB2/LINUXX8664", "db2");
        databaseTypeMappings.setProperty("DB2/LINUXZ64", "db2");
        databaseTypeMappings.setProperty("DB2/LINUXPPC64", "db2");
        databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", "db2");
        databaseTypeMappings.setProperty("DB2/400 SQL", "db2");
        databaseTypeMappings.setProperty("DB2/6000", "db2");
        databaseTypeMappings.setProperty("DB2 UDB iSeries", "db2");
        databaseTypeMappings.setProperty("DB2/AIX64", "db2");
        databaseTypeMappings.setProperty("DB2/HPUX", "db2");
        databaseTypeMappings.setProperty("DB2/HP64", "db2");
        databaseTypeMappings.setProperty("DB2/SUN", "db2");
        databaseTypeMappings.setProperty("DB2/SUN64", "db2");
        databaseTypeMappings.setProperty("DB2/PTX", "db2");
        databaseTypeMappings.setProperty("DB2/2", "db2");
        databaseTypeMappings.setProperty("DB2 UDB AS400", "db2");
        databaseTypeMappings.setProperty("CockroachDB", "cockroachdb");
        databaseTypeMappings.setProperty("YashanDB", DATABASE_TYPE_YASDB);

        return databaseTypeMappings;
    }

    protected void initEngineConfigurations() {
        this.addEngineConfiguration(this.getEngineCfgKey(), this.getEngineScopeType(), this);
    }

    protected void initDataSource() {
        if (this.dataSource == null) {
            if (this.dataSourceJndiName != null) {
                try {
                    this.dataSource = (DataSource)(new InitialContext()).lookup(this.dataSourceJndiName);
                } catch (Exception var2) {
                    throw new FlowableException("couldn't lookup datasource from " + this.dataSourceJndiName + ": " + var2.getMessage(), var2);
                }
            } else if (this.jdbcUrl != null) {
                if (this.jdbcDriver == null || this.jdbcUsername == null) {
                    throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration");
                }

                this.logger.debug("initializing datasource to db: {}", this.jdbcUrl);
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Configuring Datasource with following properties (omitted password for security)");
                    this.logger.info("datasource driver : {}", this.jdbcDriver);
                    this.logger.info("datasource url : {}", this.jdbcUrl);
                    this.logger.info("datasource user name : {}", this.jdbcUsername);
                }

                PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), this.jdbcDriver, this.jdbcUrl, this.jdbcUsername, this.jdbcPassword);
                if (this.jdbcMaxActiveConnections > 0) {
                    pooledDataSource.setPoolMaximumActiveConnections(this.jdbcMaxActiveConnections);
                }

                if (this.jdbcMaxIdleConnections > 0) {
                    pooledDataSource.setPoolMaximumIdleConnections(this.jdbcMaxIdleConnections);
                }

                if (this.jdbcMaxCheckoutTime > 0) {
                    pooledDataSource.setPoolMaximumCheckoutTime(this.jdbcMaxCheckoutTime);
                }

                if (this.jdbcMaxWaitTime > 0) {
                    pooledDataSource.setPoolTimeToWait(this.jdbcMaxWaitTime);
                }

                if (this.jdbcPingEnabled) {
                    pooledDataSource.setPoolPingEnabled(true);
                    if (this.jdbcPingQuery != null) {
                        pooledDataSource.setPoolPingQuery(this.jdbcPingQuery);
                    }

                    pooledDataSource.setPoolPingConnectionsNotUsedFor(this.jdbcPingConnectionNotUsedFor);
                }

                if (this.jdbcDefaultTransactionIsolationLevel > 0) {
                    pooledDataSource.setDefaultTransactionIsolationLevel(this.jdbcDefaultTransactionIsolationLevel);
                }

                this.dataSource = pooledDataSource;
            }
        }

        if (this.databaseType == null) {
            this.initDatabaseType();
        }

    }

    public void initDatabaseType() {
        Connection connection = null;

        try {
            connection = this.dataSource.getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            String databaseProductName = databaseMetaData.getDatabaseProductName();
            this.logger.debug("database product name: '{}'", databaseProductName);
            if ("PostgreSQL".equalsIgnoreCase(databaseProductName)) {
                PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;");
                Throwable var5 = null;

                try {
                    ResultSet resultSet = preparedStatement.executeQuery();
                    Throwable var7 = null;

                    try {
                        String version = null;
                        if (resultSet.next()) {
                            version = resultSet.getString("version");
                        }

                        if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith("CockroachDB".toLowerCase())) {
                            databaseProductName = "CockroachDB";
                            this.logger.info("CockroachDB version '{}' detected", version);
                        }
                    } catch (Throwable var51) {
                        var7 = var51;
                        throw var51;
                    } finally {
                        if (resultSet != null) {
                            if (var7 != null) {
                                try {
                                    resultSet.close();
                                } catch (Throwable var50) {
                                    var7.addSuppressed(var50);
                                }
                            } else {
                                resultSet.close();
                            }
                        }

                    }
                } catch (Throwable var53) {
                    var5 = var53;
                    throw var53;
                } finally {
                    if (preparedStatement != null) {
                        if (var5 != null) {
                            try {
                                preparedStatement.close();
                            } catch (Throwable var49) {
                                var5.addSuppressed(var49);
                            }
                        } else {
                            preparedStatement.close();
                        }
                    }

                }
            }

            this.databaseType = this.databaseTypeMappings.getProperty(databaseProductName);
            if (this.databaseType == null) {
                throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'");
            }

            this.logger.debug("using database type: {}", this.databaseType);
        } catch (SQLException var55) {
            throw new RuntimeException("Exception while initializing Database connection", var55);
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException var48) {
                this.logger.error("Exception while closing the Database connection", var48);
            }

        }

        if ("mssql".equals(this.databaseType)) {
            this.maxNrOfStatementsInBulkInsert = this.DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER;
        }

    }

    public void initSchemaManager() {
        if (this.commonSchemaManager == null) {
            this.commonSchemaManager = new CommonDbSchemaManager();
        }

    }

    public void addSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactories.put(sessionFactory.getSessionType(), sessionFactory);
    }

    public void initCommandContextFactory() {
        if (this.commandContextFactory == null) {
            this.commandContextFactory = new CommandContextFactory();
        }

    }

    public void initTransactionContextFactory() {
        if (this.transactionContextFactory == null) {
            this.transactionContextFactory = new StandaloneMybatisTransactionContextFactory();
        }

    }

    public void initCommandExecutors() {
        this.initDefaultCommandConfig();
        this.initSchemaCommandConfig();
        this.initCommandInvoker();
        this.initCommandInterceptors();
        this.initCommandExecutor();
    }

    public void initDefaultCommandConfig() {
        if (this.defaultCommandConfig == null) {
            this.defaultCommandConfig = new CommandConfig();
        }

    }

    public void initSchemaCommandConfig() {
        if (this.schemaCommandConfig == null) {
            this.schemaCommandConfig = new CommandConfig();
        }

    }

    public void initCommandInvoker() {
        if (this.commandInvoker == null) {
            this.commandInvoker = new DefaultCommandInvoker();
        }

    }

    public void initCommandInterceptors() {
        if (this.commandInterceptors == null) {
            this.commandInterceptors = new ArrayList();
            if (this.customPreCommandInterceptors != null) {
                this.commandInterceptors.addAll(this.customPreCommandInterceptors);
            }

            this.commandInterceptors.addAll(this.getDefaultCommandInterceptors());
            if (this.customPostCommandInterceptors != null) {
                this.commandInterceptors.addAll(this.customPostCommandInterceptors);
            }

            this.commandInterceptors.add(this.commandInvoker);
        }

    }

    public Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() {
        if (this.defaultCommandInterceptors == null) {
            List<CommandInterceptor> interceptors = new ArrayList();
            interceptors.add(new LogInterceptor());
            if ("cockroachdb".equals(this.databaseType)) {
                interceptors.add(new CrDbRetryInterceptor());
            }

            CommandInterceptor transactionInterceptor = this.createTransactionInterceptor();
            if (transactionInterceptor != null) {
                interceptors.add(transactionInterceptor);
            }

            if (this.commandContextFactory != null) {
                String engineCfgKey = this.getEngineCfgKey();
                CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(this.commandContextFactory, this.classLoader, this.useClassForNameClassLoading, this.clock, this.objectMapper);
                this.engineConfigurations.put(engineCfgKey, this);
                commandContextInterceptor.setEngineCfgKey(engineCfgKey);
                commandContextInterceptor.setEngineConfigurations(this.engineConfigurations);
                interceptors.add(commandContextInterceptor);
            }

            if (this.transactionContextFactory != null) {
                interceptors.add(new TransactionContextInterceptor(this.transactionContextFactory));
            }

            List<CommandInterceptor> additionalCommandInterceptors = this.getAdditionalDefaultCommandInterceptors();
            if (additionalCommandInterceptors != null) {
                interceptors.addAll(additionalCommandInterceptors);
            }

            this.defaultCommandInterceptors = interceptors;
        }

        return this.defaultCommandInterceptors;
    }

    public abstract String getEngineCfgKey();

    public abstract String getEngineScopeType();

    public List<CommandInterceptor> getAdditionalDefaultCommandInterceptors() {
        return null;
    }

    public void initCommandExecutor() {
        if (this.commandExecutor == null) {
            CommandInterceptor first = this.initInterceptorChain(this.commandInterceptors);
            this.commandExecutor = new CommandExecutorImpl(this.getDefaultCommandConfig(), first);
        }

    }

    public CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) {
        if (chain != null && !chain.isEmpty()) {
            for(int i = 0; i < chain.size() - 1; ++i) {
                ((CommandInterceptor)chain.get(i)).setNext((CommandInterceptor)chain.get(i + 1));
            }

            return (CommandInterceptor)chain.get(0);
        } else {
            throw new FlowableException("invalid command interceptor chain configuration: " + chain);
        }
    }

    public abstract CommandInterceptor createTransactionInterceptor();

    public void initBeans() {
        if (this.beans == null) {
            this.beans = new HashMap();
        }

    }

    public void initIdGenerator() {
        if (this.idGenerator == null) {
            this.idGenerator = new StrongUuidGenerator();
        }

    }

    public void initObjectMapper() {
        if (this.objectMapper == null) {
            this.objectMapper = new ObjectMapper();
            this.objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        }

    }

    public void initClock() {
        if (this.clock == null) {
            this.clock = new DefaultClockImpl();
        }

    }

    public void initDataManagers() {
        if (this.propertyDataManager == null) {
            this.propertyDataManager = new MybatisPropertyDataManager(this.idGenerator);
        }

        if (this.byteArrayDataManager == null) {
            this.byteArrayDataManager = new MybatisByteArrayDataManager(this.idGenerator);
        }

    }

    public void initEntityManagers() {
        if (this.propertyEntityManager == null) {
            this.propertyEntityManager = new PropertyEntityManagerImpl(this, this.propertyDataManager);
        }

        if (this.byteArrayEntityManager == null) {
            this.byteArrayEntityManager = new ByteArrayEntityManagerImpl(this.byteArrayDataManager, this.getEngineCfgKey(), this::getEventDispatcher);
        }

        if (this.tableDataManager == null) {
            this.tableDataManager = new TableDataManagerImpl(this);
        }

    }

    protected void initService(Object service) {
        if (service instanceof CommonEngineServiceImpl) {
            ((CommonEngineServiceImpl)service).setCommandExecutor(this.commandExecutor);
        }

    }

    public void initSessionFactories() {
        if (this.sessionFactories == null) {
            this.sessionFactories = new HashMap();
            if (this.usingRelationalDatabase) {
                this.initDbSqlSessionFactory();
            }

            this.addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class));
            if (this.isLoggingSessionEnabled() && !this.sessionFactories.containsKey(LoggingSession.class)) {
                LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory();
                loggingSessionFactory.setLoggingListener(this.loggingListener);
                loggingSessionFactory.setObjectMapper(this.objectMapper);
                this.sessionFactories.put(LoggingSession.class, loggingSessionFactory);
            }

            this.commandContextFactory.setSessionFactories(this.sessionFactories);
        } else if (this.usingRelationalDatabase) {
            this.initDbSqlSessionFactoryEntitySettings();
        }

        if (this.customSessionFactories != null) {
            Iterator var3 = this.customSessionFactories.iterator();

            while(var3.hasNext()) {
                SessionFactory sessionFactory = (SessionFactory)var3.next();
                this.addSessionFactory(sessionFactory);
            }
        }

    }

    public void initDbSqlSessionFactory() {
        if (this.dbSqlSessionFactory == null) {
            this.dbSqlSessionFactory = this.createDbSqlSessionFactory();
        }

        this.dbSqlSessionFactory.setDatabaseType(this.databaseType);
        this.dbSqlSessionFactory.setSqlSessionFactory(this.sqlSessionFactory);
        this.dbSqlSessionFactory.setDbHistoryUsed(this.isDbHistoryUsed);
        this.dbSqlSessionFactory.setDatabaseTablePrefix(this.databaseTablePrefix);
        this.dbSqlSessionFactory.setTablePrefixIsSchema(this.tablePrefixIsSchema);
        this.dbSqlSessionFactory.setDatabaseCatalog(this.databaseCatalog);
        this.dbSqlSessionFactory.setDatabaseSchema(this.databaseSchema);
        this.dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(this.maxNrOfStatementsInBulkInsert);
        this.initDbSqlSessionFactoryEntitySettings();
        this.addSessionFactory(this.dbSqlSessionFactory);
    }

    public DbSqlSessionFactory createDbSqlSessionFactory() {
        return new DbSqlSessionFactory(this.usePrefixId);
    }

    protected abstract void initDbSqlSessionFactoryEntitySettings();

    protected void defaultInitDbSqlSessionFactoryEntitySettings(List<Class<? extends Entity>> insertOrder, List<Class<? extends Entity>> deleteOrder) {
        Iterator var3;
        Class clazz;
        if (insertOrder != null) {
            var3 = insertOrder.iterator();

            while(var3.hasNext()) {
                clazz = (Class)var3.next();
                this.dbSqlSessionFactory.getInsertionOrder().add(clazz);
                if (this.isBulkInsertEnabled) {
                    this.dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz);
                }
            }
        }

        if (deleteOrder != null) {
            var3 = deleteOrder.iterator();

            while(var3.hasNext()) {
                clazz = (Class)var3.next();
                this.dbSqlSessionFactory.getDeletionOrder().add(clazz);
            }
        }

    }

    public void initTransactionFactory() {
        if (this.transactionFactory == null) {
            if (this.transactionsExternallyManaged) {
                this.transactionFactory = new ManagedTransactionFactory();
                Properties properties = new Properties();
                properties.put("closeConnection", "false");
                this.transactionFactory.setProperties(properties);
            } else {
                this.transactionFactory = new JdbcTransactionFactory();
            }
        }

    }

    public void initSqlSessionFactory() {
        if (this.sqlSessionFactory == null) {
            InputStream inputStream = null;

            try {
                inputStream = this.getMyBatisXmlConfigurationStream();
                Environment environment = new Environment("default", this.transactionFactory, this.dataSource);
                Reader reader = new InputStreamReader(inputStream);
                Properties properties = new Properties();
                properties.put("prefix", this.databaseTablePrefix);
                String wildcardEscapeClause = "";
                if (this.databaseWildcardEscapeCharacter != null && this.databaseWildcardEscapeCharacter.length() != 0) {
                    wildcardEscapeClause = " escape '" + this.databaseWildcardEscapeCharacter + "'";
                }

                properties.put("wildcardEscapeClause", wildcardEscapeClause);
                properties.put("limitBefore", "");
                properties.put("limitAfter", "");
                properties.put("limitBetween", "");
                properties.put("limitBeforeNativeQuery", "");
                properties.put("limitAfterNativeQuery", "");
                properties.put("blobType", "BLOB");
                properties.put("boolValue", "TRUE");
                if (this.databaseType != null) {
                    properties.load(this.getResourceAsStream(this.pathToEngineDbProperties()));
                }

                Configuration configuration = this.initMybatisConfiguration(environment, reader, properties);
                this.sqlSessionFactory = new DefaultSqlSessionFactory(configuration);
            } catch (Exception var10) {
                throw new FlowableException("Error while building ibatis SqlSessionFactory: " + var10.getMessage(), var10);
            } finally {
                IoUtil.closeSilently(inputStream);
            }
        } else {
            this.applyCustomMybatisCustomizations(this.sqlSessionFactory.getConfiguration());
        }

    }

    public String pathToEngineDbProperties() {
        return "org/flowable/common/db/properties/" + this.databaseType + ".properties";
    }

    public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) {
        XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties);
        Configuration configuration = parser.getConfiguration();
        if (this.databaseType != null) {
            configuration.setDatabaseId(this.databaseType);
        }

        configuration.setEnvironment(environment);
        this.initMybatisTypeHandlers(configuration);
        this.initCustomMybatisInterceptors(configuration);
        if (this.isEnableLogSqlExecutionTime()) {
            this.initMyBatisLogSqlExecutionTimePlugin(configuration);
        }

        configuration = this.parseMybatisConfiguration(parser);
        return configuration;
    }

    public void initCustomMybatisMappers(Configuration configuration) {
        if (this.getCustomMybatisMappers() != null) {
            Iterator var2 = this.getCustomMybatisMappers().iterator();

            while(var2.hasNext()) {
                Class<?> clazz = (Class)var2.next();
                if (!configuration.hasMapper(clazz)) {
                    configuration.addMapper(clazz);
                }
            }
        }

    }

    public void initMybatisTypeHandlers(Configuration configuration) {
        TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry();
        handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler());
        handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler());
    }

    public void initCustomMybatisInterceptors(Configuration configuration) {
        if (this.customMybatisInterceptors != null) {
            Iterator var2 = this.customMybatisInterceptors.iterator();

            while(var2.hasNext()) {
                Interceptor interceptor = (Interceptor)var2.next();
                configuration.addInterceptor(interceptor);
            }
        }

    }

    public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) {
        configuration.addInterceptor(new LogSqlExecutionTimePlugin());
    }

    public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) {
        Configuration configuration = parser.parse();
        this.applyCustomMybatisCustomizations(configuration);
        return configuration;
    }

    protected void applyCustomMybatisCustomizations(Configuration configuration) {
        this.initCustomMybatisMappers(configuration);
        Iterator var2;
        if (this.dependentEngineMybatisTypeAliasConfigs != null) {
            var2 = this.dependentEngineMybatisTypeAliasConfigs.iterator();

            while(var2.hasNext()) {
                MybatisTypeAliasConfigurator typeAliasConfig = (MybatisTypeAliasConfigurator)var2.next();
                typeAliasConfig.configure(configuration.getTypeAliasRegistry());
            }
        }

        if (this.dependentEngineMybatisTypeHandlerConfigs != null) {
            var2 = this.dependentEngineMybatisTypeHandlerConfigs.iterator();

            while(var2.hasNext()) {
                MybatisTypeHandlerConfigurator typeHandlerConfig = (MybatisTypeHandlerConfigurator)var2.next();
                typeHandlerConfig.configure(configuration.getTypeHandlerRegistry());
            }
        }

        this.parseDependentEngineMybatisXMLMappers(configuration);
        this.parseCustomMybatisXMLMappers(configuration);
    }

    public void parseCustomMybatisXMLMappers(Configuration configuration) {
        if (this.getCustomMybatisXMLMappers() != null) {
            Iterator var2 = this.getCustomMybatisXMLMappers().iterator();

            while(var2.hasNext()) {
                String resource = (String)var2.next();
                this.parseMybatisXmlMapping(configuration, resource);
            }
        }

    }

    public void parseDependentEngineMybatisXMLMappers(Configuration configuration) {
        if (this.getDependentEngineMyBatisXmlMappers() != null) {
            Iterator var2 = this.getDependentEngineMyBatisXmlMappers().iterator();

            while(var2.hasNext()) {
                String resource = (String)var2.next();
                this.parseMybatisXmlMapping(configuration, resource);
            }
        }

    }

    protected void parseMybatisXmlMapping(Configuration configuration, String resource) {
        XMLMapperBuilder mapperParser = new XMLMapperBuilder(this.getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments());
        mapperParser.parse();
    }

    protected InputStream getResourceAsStream(String resource) {
        ClassLoader classLoader = this.getClassLoader();
        return classLoader != null ? this.getClassLoader().getResourceAsStream(resource) : this.getClass().getClassLoader().getResourceAsStream(resource);
    }

    public void setMybatisMappingFile(String file) {
        this.mybatisMappingFile = file;
    }

    public String getMybatisMappingFile() {
        return this.mybatisMappingFile;
    }

    public abstract InputStream getMyBatisXmlConfigurationStream();

    public void initConfigurators() {
        this.allConfigurators = new ArrayList();
        this.allConfigurators.addAll(this.getEngineSpecificEngineConfigurators());
        if (this.configurators != null) {
            this.allConfigurators.addAll(this.configurators);
        }

        if (this.enableConfiguratorServiceLoader) {
            ClassLoader classLoader = this.getClassLoader();
            if (classLoader == null) {
                classLoader = ReflectUtil.getClassLoader();
            }

            ServiceLoader<EngineConfigurator> configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader);
            int nrOfServiceLoadedConfigurators = 0;

            Iterator var4;
            EngineConfigurator configurator;
            for(var4 = configuratorServiceLoader.iterator(); var4.hasNext(); ++nrOfServiceLoadedConfigurators) {
                configurator = (EngineConfigurator)var4.next();
                this.allConfigurators.add(configurator);
            }

            if (nrOfServiceLoadedConfigurators > 0) {
                this.logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : "");
            }

            if (!this.allConfigurators.isEmpty()) {
                this.allConfigurators.sort(new Comparator<EngineConfigurator>() {
                    public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) {
                        int priority1 = configurator1.getPriority();
                        int priority2 = configurator2.getPriority();
                        if (priority1 < priority2) {
                            return -1;
                        } else {
                            return priority1 > priority2 ? 1 : 0;
                        }
                    }
                });
                this.logger.info("Found {} Engine Configurators in total:", this.allConfigurators.size());
                var4 = this.allConfigurators.iterator();

                while(var4.hasNext()) {
                    configurator = (EngineConfigurator)var4.next();
                    this.logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority());
                }
            }
        }

    }

    public void close() {
        if (this.forceCloseMybatisConnectionPool && this.dataSource instanceof PooledDataSource) {
            ((PooledDataSource)this.dataSource).forceCloseAll();
        }

    }

    protected List<EngineConfigurator> getEngineSpecificEngineConfigurators() {
        return Collections.emptyList();
    }

    public void configuratorsBeforeInit() {
        Iterator var1 = this.allConfigurators.iterator();

        while(var1.hasNext()) {
            EngineConfigurator configurator = (EngineConfigurator)var1.next();
            this.logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority());
            configurator.beforeInit(this);
        }

    }

    public void configuratorsAfterInit() {
        Iterator var1 = this.allConfigurators.iterator();

        while(var1.hasNext()) {
            EngineConfigurator configurator = (EngineConfigurator)var1.next();
            this.logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority());
            configurator.configure(this);
        }

    }

    public LockManager getLockManager(String lockName) {
        return new LockManagerImpl(this.commandExecutor, lockName, this.getLockPollRate(), this.getEngineCfgKey());
    }

    public abstract String getEngineName();

    public ClassLoader getClassLoader() {
        return this.classLoader;
    }

    public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
        return this;
    }

    public boolean isUseClassForNameClassLoading() {
        return this.useClassForNameClassLoading;
    }

    public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) {
        this.useClassForNameClassLoading = useClassForNameClassLoading;
        return this;
    }

    public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) {
        if (this.engineLifecycleListeners == null) {
            this.engineLifecycleListeners = new ArrayList();
        }

        this.engineLifecycleListeners.add(engineLifecycleListener);
    }

    public List<EngineLifecycleListener> getEngineLifecycleListeners() {
        return this.engineLifecycleListeners;
    }

    public AbstractEngineConfiguration setEngineLifecycleListeners(List<EngineLifecycleListener> engineLifecycleListeners) {
        this.engineLifecycleListeners = engineLifecycleListeners;
        return this;
    }

    public String getDatabaseType() {
        return this.databaseType;
    }

    public AbstractEngineConfiguration setDatabaseType(String databaseType) {
        this.databaseType = databaseType;
        return this;
    }

    public DataSource getDataSource() {
        return this.dataSource;
    }

    public AbstractEngineConfiguration setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        return this;
    }

    public SchemaManager getSchemaManager() {
        return this.schemaManager;
    }

    public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) {
        this.schemaManager = schemaManager;
        return this;
    }

    public SchemaManager getCommonSchemaManager() {
        return this.commonSchemaManager;
    }

    public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) {
        this.commonSchemaManager = commonSchemaManager;
        return this;
    }

    public Command<Void> getSchemaManagementCmd() {
        return this.schemaManagementCmd;
    }

    public AbstractEngineConfiguration setSchemaManagementCmd(Command<Void> schemaManagementCmd) {
        this.schemaManagementCmd = schemaManagementCmd;
        return this;
    }

    public String getJdbcDriver() {
        return this.jdbcDriver;
    }

    public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) {
        this.jdbcDriver = jdbcDriver;
        return this;
    }

    public String getJdbcUrl() {
        return this.jdbcUrl;
    }

    public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
        return this;
    }

    public String getJdbcUsername() {
        return this.jdbcUsername;
    }

    public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) {
        this.jdbcUsername = jdbcUsername;
        return this;
    }

    public String getJdbcPassword() {
        return this.jdbcPassword;
    }

    public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) {
        this.jdbcPassword = jdbcPassword;
        return this;
    }

    public int getJdbcMaxActiveConnections() {
        return this.jdbcMaxActiveConnections;
    }

    public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) {
        this.jdbcMaxActiveConnections = jdbcMaxActiveConnections;
        return this;
    }

    public int getJdbcMaxIdleConnections() {
        return this.jdbcMaxIdleConnections;
    }

    public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) {
        this.jdbcMaxIdleConnections = jdbcMaxIdleConnections;
        return this;
    }

    public int getJdbcMaxCheckoutTime() {
        return this.jdbcMaxCheckoutTime;
    }

    public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) {
        this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime;
        return this;
    }

    public int getJdbcMaxWaitTime() {
        return this.jdbcMaxWaitTime;
    }

    public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) {
        this.jdbcMaxWaitTime = jdbcMaxWaitTime;
        return this;
    }

    public boolean isJdbcPingEnabled() {
        return this.jdbcPingEnabled;
    }

    public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) {
        this.jdbcPingEnabled = jdbcPingEnabled;
        return this;
    }

    public int getJdbcPingConnectionNotUsedFor() {
        return this.jdbcPingConnectionNotUsedFor;
    }

    public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) {
        this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor;
        return this;
    }

    public int getJdbcDefaultTransactionIsolationLevel() {
        return this.jdbcDefaultTransactionIsolationLevel;
    }

    public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) {
        this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel;
        return this;
    }

    public String getJdbcPingQuery() {
        return this.jdbcPingQuery;
    }

    public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) {
        this.jdbcPingQuery = jdbcPingQuery;
        return this;
    }

    public String getDataSourceJndiName() {
        return this.dataSourceJndiName;
    }

    public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) {
        this.dataSourceJndiName = dataSourceJndiName;
        return this;
    }

    public CommandConfig getSchemaCommandConfig() {
        return this.schemaCommandConfig;
    }

    public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) {
        this.schemaCommandConfig = schemaCommandConfig;
        return this;
    }

    public boolean isTransactionsExternallyManaged() {
        return this.transactionsExternallyManaged;
    }

    public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) {
        this.transactionsExternallyManaged = transactionsExternallyManaged;
        return this;
    }

    public Map<Object, Object> getBeans() {
        return this.beans;
    }

    public AbstractEngineConfiguration setBeans(Map<Object, Object> beans) {
        this.beans = beans;
        return this;
    }

    public IdGenerator getIdGenerator() {
        return this.idGenerator;
    }

    public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) {
        this.idGenerator = idGenerator;
        return this;
    }

    public boolean isUsePrefixId() {
        return this.usePrefixId;
    }

    public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) {
        this.usePrefixId = usePrefixId;
        return this;
    }

    public String getXmlEncoding() {
        return this.xmlEncoding;
    }

    public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) {
        this.xmlEncoding = xmlEncoding;
        return this;
    }

    public CommandConfig getDefaultCommandConfig() {
        return this.defaultCommandConfig;
    }

    public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) {
        this.defaultCommandConfig = defaultCommandConfig;
        return this;
    }

    public CommandExecutor getCommandExecutor() {
        return this.commandExecutor;
    }

    public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) {
        this.commandExecutor = commandExecutor;
        return this;
    }

    public CommandContextFactory getCommandContextFactory() {
        return this.commandContextFactory;
    }

    public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) {
        this.commandContextFactory = commandContextFactory;
        return this;
    }

    public CommandInterceptor getCommandInvoker() {
        return this.commandInvoker;
    }

    public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) {
        this.commandInvoker = commandInvoker;
        return this;
    }

    public AgendaOperationRunner getAgendaOperationRunner() {
        return this.agendaOperationRunner;
    }

    public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) {
        this.agendaOperationRunner = agendaOperationRunner;
        return this;
    }

    public List<CommandInterceptor> getCustomPreCommandInterceptors() {
        return this.customPreCommandInterceptors;
    }

    public AbstractEngineConfiguration setCustomPreCommandInterceptors(List<CommandInterceptor> customPreCommandInterceptors) {
        this.customPreCommandInterceptors = customPreCommandInterceptors;
        return this;
    }

    public List<CommandInterceptor> getCustomPostCommandInterceptors() {
        return this.customPostCommandInterceptors;
    }

    public AbstractEngineConfiguration setCustomPostCommandInterceptors(List<CommandInterceptor> customPostCommandInterceptors) {
        this.customPostCommandInterceptors = customPostCommandInterceptors;
        return this;
    }

    public List<CommandInterceptor> getCommandInterceptors() {
        return this.commandInterceptors;
    }

    public AbstractEngineConfiguration setCommandInterceptors(List<CommandInterceptor> commandInterceptors) {
        this.commandInterceptors = commandInterceptors;
        return this;
    }

    public Map<String, AbstractEngineConfiguration> getEngineConfigurations() {
        return this.engineConfigurations;
    }

    public AbstractEngineConfiguration setEngineConfigurations(Map<String, AbstractEngineConfiguration> engineConfigurations) {
        this.engineConfigurations = engineConfigurations;
        return this;
    }

    public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) {
        if (this.engineConfigurations == null) {
            this.engineConfigurations = new HashMap();
        }

        this.engineConfigurations.put(key, engineConfiguration);
        this.engineConfigurations.put(scopeType, engineConfiguration);
    }

    public Map<String, AbstractServiceConfiguration> getServiceConfigurations() {
        return this.serviceConfigurations;
    }

    public AbstractEngineConfiguration setServiceConfigurations(Map<String, AbstractServiceConfiguration> serviceConfigurations) {
        this.serviceConfigurations = serviceConfigurations;
        return this;
    }

    public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) {
        if (this.serviceConfigurations == null) {
            this.serviceConfigurations = new HashMap();
        }

        this.serviceConfigurations.put(key, serviceConfiguration);
    }

    public Map<String, EventRegistryEventConsumer> getEventRegistryEventConsumers() {
        return this.eventRegistryEventConsumers;
    }

    public AbstractEngineConfiguration setEventRegistryEventConsumers(Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers) {
        this.eventRegistryEventConsumers = eventRegistryEventConsumers;
        return this;
    }

    public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) {
        if (this.eventRegistryEventConsumers == null) {
            this.eventRegistryEventConsumers = new HashMap();
        }

        this.eventRegistryEventConsumers.put(key, eventRegistryEventConsumer);
    }

    public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection<? extends CommandInterceptor> defaultCommandInterceptors) {
        this.defaultCommandInterceptors = defaultCommandInterceptors;
        return this;
    }

    public SqlSessionFactory getSqlSessionFactory() {
        return this.sqlSessionFactory;
    }

    public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
        return this;
    }

    public boolean isDbHistoryUsed() {
        return this.isDbHistoryUsed;
    }

    public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) {
        this.isDbHistoryUsed = isDbHistoryUsed;
        return this;
    }

    public DbSqlSessionFactory getDbSqlSessionFactory() {
        return this.dbSqlSessionFactory;
    }

    public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) {
        this.dbSqlSessionFactory = dbSqlSessionFactory;
        return this;
    }

    public TransactionFactory getTransactionFactory() {
        return this.transactionFactory;
    }

    public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) {
        this.transactionFactory = transactionFactory;
        return this;
    }

    public TransactionContextFactory getTransactionContextFactory() {
        return this.transactionContextFactory;
    }

    public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) {
        this.transactionContextFactory = transactionContextFactory;
        return this;
    }

    public int getMaxNrOfStatementsInBulkInsert() {
        return this.maxNrOfStatementsInBulkInsert;
    }

    public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) {
        this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert;
        return this;
    }

    public boolean isBulkInsertEnabled() {
        return this.isBulkInsertEnabled;
    }

    public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) {
        this.isBulkInsertEnabled = isBulkInsertEnabled;
        return this;
    }

    public Set<Class<?>> getCustomMybatisMappers() {
        return this.customMybatisMappers;
    }

    public AbstractEngineConfiguration setCustomMybatisMappers(Set<Class<?>> customMybatisMappers) {
        this.customMybatisMappers = customMybatisMappers;
        return this;
    }

    public Set<String> getCustomMybatisXMLMappers() {
        return this.customMybatisXMLMappers;
    }

    public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set<String> customMybatisXMLMappers) {
        this.customMybatisXMLMappers = customMybatisXMLMappers;
        return this;
    }

    public Set<String> getDependentEngineMyBatisXmlMappers() {
        return this.dependentEngineMyBatisXmlMappers;
    }

    public AbstractEngineConfiguration setCustomMybatisInterceptors(List<Interceptor> customMybatisInterceptors) {
        this.customMybatisInterceptors = customMybatisInterceptors;
        return this;
    }

    public List<Interceptor> getCustomMybatisInterceptors() {
        return this.customMybatisInterceptors;
    }

    public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set<String> dependentEngineMyBatisXmlMappers) {
        this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers;
        return this;
    }

    public List<MybatisTypeAliasConfigurator> getDependentEngineMybatisTypeAliasConfigs() {
        return this.dependentEngineMybatisTypeAliasConfigs;
    }

    public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs) {
        this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs;
        return this;
    }

    public List<MybatisTypeHandlerConfigurator> getDependentEngineMybatisTypeHandlerConfigs() {
        return this.dependentEngineMybatisTypeHandlerConfigs;
    }

    public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs) {
        this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs;
        return this;
    }

    public List<SessionFactory> getCustomSessionFactories() {
        return this.customSessionFactories;
    }

    public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) {
        if (this.customSessionFactories == null) {
            this.customSessionFactories = new ArrayList();
        }

        this.customSessionFactories.add(sessionFactory);
        return this;
    }

    public AbstractEngineConfiguration setCustomSessionFactories(List<SessionFactory> customSessionFactories) {
        this.customSessionFactories = customSessionFactories;
        return this;
    }

    public boolean isUsingRelationalDatabase() {
        return this.usingRelationalDatabase;
    }

    public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) {
        this.usingRelationalDatabase = usingRelationalDatabase;
        return this;
    }

    public boolean isUsingSchemaMgmt() {
        return this.usingSchemaMgmt;
    }

    public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) {
        this.usingSchemaMgmt = usingSchema;
        return this;
    }

    public String getDatabaseTablePrefix() {
        return this.databaseTablePrefix;
    }

    public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) {
        this.databaseTablePrefix = databaseTablePrefix;
        return this;
    }

    public String getDatabaseWildcardEscapeCharacter() {
        return this.databaseWildcardEscapeCharacter;
    }

    public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) {
        this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter;
        return this;
    }

    public String getDatabaseCatalog() {
        return this.databaseCatalog;
    }

    public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) {
        this.databaseCatalog = databaseCatalog;
        return this;
    }

    public String getDatabaseSchema() {
        return this.databaseSchema;
    }

    public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) {
        this.databaseSchema = databaseSchema;
        return this;
    }

    public boolean isTablePrefixIsSchema() {
        return this.tablePrefixIsSchema;
    }

    public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) {
        this.tablePrefixIsSchema = tablePrefixIsSchema;
        return this;
    }

    public boolean isAlwaysLookupLatestDefinitionVersion() {
        return this.alwaysLookupLatestDefinitionVersion;
    }

    public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) {
        this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion;
        return this;
    }

    public boolean isFallbackToDefaultTenant() {
        return this.fallbackToDefaultTenant;
    }

    public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) {
        this.fallbackToDefaultTenant = fallbackToDefaultTenant;
        return this;
    }

    /** @deprecated */
    @Deprecated
    public String getDefaultTenantValue() {
        return this.getDefaultTenantProvider().getDefaultTenant((String)null, (String)null, (String)null);
    }

    public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) {
        this.defaultTenantProvider = (tenantId, scope, scopeKey) -> {
            return defaultTenantValue;
        };
        return this;
    }

    public DefaultTenantProvider getDefaultTenantProvider() {
        return this.defaultTenantProvider;
    }

    public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) {
        this.defaultTenantProvider = defaultTenantProvider;
        return this;
    }

    public boolean isEnableLogSqlExecutionTime() {
        return this.enableLogSqlExecutionTime;
    }

    public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) {
        this.enableLogSqlExecutionTime = enableLogSqlExecutionTime;
    }

    public Map<Class<?>, SessionFactory> getSessionFactories() {
        return this.sessionFactories;
    }

    public AbstractEngineConfiguration setSessionFactories(Map<Class<?>, SessionFactory> sessionFactories) {
        this.sessionFactories = sessionFactories;
        return this;
    }

    public String getDatabaseSchemaUpdate() {
        return this.databaseSchemaUpdate;
    }

    public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) {
        this.databaseSchemaUpdate = databaseSchemaUpdate;
        return this;
    }

    public boolean isUseLockForDatabaseSchemaUpdate() {
        return this.useLockForDatabaseSchemaUpdate;
    }

    public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) {
        this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate;
        return this;
    }

    public boolean isEnableEventDispatcher() {
        return this.enableEventDispatcher;
    }

    public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) {
        this.enableEventDispatcher = enableEventDispatcher;
        return this;
    }

    public FlowableEventDispatcher getEventDispatcher() {
        return this.eventDispatcher;
    }

    public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) {
        this.eventDispatcher = eventDispatcher;
        return this;
    }

    public List<FlowableEventListener> getEventListeners() {
        return this.eventListeners;
    }

    public AbstractEngineConfiguration setEventListeners(List<FlowableEventListener> eventListeners) {
        this.eventListeners = eventListeners;
        return this;
    }

    public Map<String, List<FlowableEventListener>> getTypedEventListeners() {
        return this.typedEventListeners;
    }

    public AbstractEngineConfiguration setTypedEventListeners(Map<String, List<FlowableEventListener>> typedEventListeners) {
        this.typedEventListeners = typedEventListeners;
        return this;
    }

    public List<EventDispatchAction> getAdditionalEventDispatchActions() {
        return this.additionalEventDispatchActions;
    }

    public AbstractEngineConfiguration setAdditionalEventDispatchActions(List<EventDispatchAction> additionalEventDispatchActions) {
        this.additionalEventDispatchActions = additionalEventDispatchActions;
        return this;
    }

    public void initEventDispatcher() {
        if (this.eventDispatcher == null) {
            this.eventDispatcher = new FlowableEventDispatcherImpl();
        }

        this.initAdditionalEventDispatchActions();
        this.eventDispatcher.setEnabled(this.enableEventDispatcher);
        this.initEventListeners();
        this.initTypedEventListeners();
    }

    protected void initEventListeners() {
        if (this.eventListeners != null) {
            Iterator var1 = this.eventListeners.iterator();

            while(var1.hasNext()) {
                FlowableEventListener listenerToAdd = (FlowableEventListener)var1.next();
                this.eventDispatcher.addEventListener(listenerToAdd);
            }
        }

    }

    protected void initAdditionalEventDispatchActions() {
        if (this.additionalEventDispatchActions == null) {
            this.additionalEventDispatchActions = new ArrayList();
        }

    }

    protected void initTypedEventListeners() {
        if (this.typedEventListeners != null) {
            Iterator var1 = this.typedEventListeners.entrySet().iterator();

            while(var1.hasNext()) {
                Entry<String, List<FlowableEventListener>> listenersToAdd = (Entry)var1.next();
                FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString((String)listenersToAdd.getKey());
                Iterator var4 = ((List)listenersToAdd.getValue()).iterator();

                while(var4.hasNext()) {
                    FlowableEventListener listenerToAdd = (FlowableEventListener)var4.next();
                    this.eventDispatcher.addEventListener(listenerToAdd, types);
                }
            }
        }

    }

    public boolean isLoggingSessionEnabled() {
        return this.loggingListener != null;
    }

    public LoggingListener getLoggingListener() {
        return this.loggingListener;
    }

    public void setLoggingListener(LoggingListener loggingListener) {
        this.loggingListener = loggingListener;
    }

    public Clock getClock() {
        return this.clock;
    }

    public AbstractEngineConfiguration setClock(Clock clock) {
        this.clock = clock;
        return this;
    }

    public ObjectMapper getObjectMapper() {
        return this.objectMapper;
    }

    public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
        return this;
    }

    public int getMaxLengthString() {
        if (this.maxLengthStringVariableType == -1) {
            return "oracle".equalsIgnoreCase(this.databaseType) ? 2000 : 4000;
        } else {
            return this.maxLengthStringVariableType;
        }
    }

    public int getMaxLengthStringVariableType() {
        return this.maxLengthStringVariableType;
    }

    public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) {
        this.maxLengthStringVariableType = maxLengthStringVariableType;
        return this;
    }

    public PropertyDataManager getPropertyDataManager() {
        return this.propertyDataManager;
    }

    public Duration getLockPollRate() {
        return this.lockPollRate;
    }

    public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) {
        this.lockPollRate = lockPollRate;
        return this;
    }

    public Duration getSchemaLockWaitTime() {
        return this.schemaLockWaitTime;
    }

    public void setSchemaLockWaitTime(Duration schemaLockWaitTime) {
        this.schemaLockWaitTime = schemaLockWaitTime;
    }

    public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) {
        this.propertyDataManager = propertyDataManager;
        return this;
    }

    public PropertyEntityManager getPropertyEntityManager() {
        return this.propertyEntityManager;
    }

    public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) {
        this.propertyEntityManager = propertyEntityManager;
        return this;
    }

    public ByteArrayDataManager getByteArrayDataManager() {
        return this.byteArrayDataManager;
    }

    public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) {
        this.byteArrayDataManager = byteArrayDataManager;
        return this;
    }

    public ByteArrayEntityManager getByteArrayEntityManager() {
        return this.byteArrayEntityManager;
    }

    public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) {
        this.byteArrayEntityManager = byteArrayEntityManager;
        return this;
    }

    public TableDataManager getTableDataManager() {
        return this.tableDataManager;
    }

    public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) {
        this.tableDataManager = tableDataManager;
        return this;
    }

    public List<EngineDeployer> getDeployers() {
        return this.deployers;
    }

    public AbstractEngineConfiguration setDeployers(List<EngineDeployer> deployers) {
        this.deployers = deployers;
        return this;
    }

    public List<EngineDeployer> getCustomPreDeployers() {
        return this.customPreDeployers;
    }

    public AbstractEngineConfiguration setCustomPreDeployers(List<EngineDeployer> customPreDeployers) {
        this.customPreDeployers = customPreDeployers;
        return this;
    }

    public List<EngineDeployer> getCustomPostDeployers() {
        return this.customPostDeployers;
    }

    public AbstractEngineConfiguration setCustomPostDeployers(List<EngineDeployer> customPostDeployers) {
        this.customPostDeployers = customPostDeployers;
        return this;
    }

    public boolean isEnableConfiguratorServiceLoader() {
        return this.enableConfiguratorServiceLoader;
    }

    public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) {
        this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader;
        return this;
    }

    public List<EngineConfigurator> getConfigurators() {
        return this.configurators;
    }

    public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) {
        if (this.configurators == null) {
            this.configurators = new ArrayList();
        }

        this.configurators.add(configurator);
        return this;
    }

    public List<EngineConfigurator> getAllConfigurators() {
        return this.allConfigurators;
    }

    public AbstractEngineConfiguration setConfigurators(List<EngineConfigurator> configurators) {
        this.configurators = configurators;
        return this;
    }

    public EngineConfigurator getIdmEngineConfigurator() {
        return this.idmEngineConfigurator;
    }

    public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) {
        this.idmEngineConfigurator = idmEngineConfigurator;
        return this;
    }

    public EngineConfigurator getEventRegistryConfigurator() {
        return this.eventRegistryConfigurator;
    }

    public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) {
        this.eventRegistryConfigurator = eventRegistryConfigurator;
        return this;
    }

    public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) {
        this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool;
        return this;
    }

    public boolean isForceCloseMybatisConnectionPool() {
        return this.forceCloseMybatisConnectionPool;
    }
}

3.3.2.4 增加yasdb.properties

增加yasdb.properties,重写flwoable框架的分页语句,并将boolean映射为0和1
新建package(org\flowable\common\db\properties)–>新建yasdb.properties
yasdb.properties

limitBefore=select RES.* from ( select RES.*, rownum as rnum from (
limitAfter= ) RES where ROWNUM < #{lastRow} ) RES where rnum >= #{firstRow}
boolValue=1

3.3.2.5 flowable 框架sql改写

方案介绍

  1. 在resource文件夹下,新建源码对应的package存放分别sql文件。
  2. 使用迁移工具直接将其他数据库数据迁移到Yashandb, 设置不自动建表,启动flowable

flowable框架使用sql,参考github
https://github.com/flowable/flowable-engine/blob/flowable-release-6.8.0/distro/sql/create/all/flowable.oracle.all.create.sql

常见报错

  1. Caused by: org.flowable.common.engine.api.FlowableException: couldn’t deduct database type from database product name ‘YashanDB’

默认flowable框架不识别Yashandb,需要重写并编译org.flowable.common.engine.impl.AbstractEngineConfiguration类

  1. 找不到xxx.yasdb.xx.sql

根据源码的sql文件做sql改写。在resources文件夹,添加特定功能的sql文件(注意package名需要跟源码里面的路径相同)

  1. 第二次启动会报错表已存在。
    1. 将flowable相关的表提前创建。在application.yml里面, 设置database-schema-update: False
    2. 删除flowable相关的表,设置database-schema-update:True

github地址:
https://github.com/xxjiafu/flowable6.8_YAS.git

flowable github地址
https://github.com/flowable/flowable-engine/blob/flowable-release-6.8.0/distro/sql/create/all/flowable.oracle.all.create.sql

flowable框架的表结构字段说明
http://t.csdnimg.cn/hlu6x

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值