/**
   * convert an xml element in FlushStrategy value
   *
   * @param reader the StAX reader
   * @return the flush strategy represention
   * @throws XMLStreamException StAX exception
   * @throws ParserException in case it isn't a number
   */
  protected FlushStrategy elementAsFlushStrategy(XMLStreamReader reader)
      throws XMLStreamException, ParserException {
    String elementtext = rawElementText(reader);
    FlushStrategy result = FlushStrategy.forName(getSubstitutionValue(elementtext));

    if (result != FlushStrategy.UNKNOWN) return result;

    throw new ParserException(bundle.notValidFlushStrategy(elementtext));
  }
  public static ModifiableConnDef buildConnectionDefinitionObject(ModelNode operation)
      throws ValidateException {
    Map<String, String> configProperties = new HashMap<String, String>(0);
    //        if (operation.hasDefined(CONFIG_PROPERTIES.getName())) {
    //            configProperties = new HashMap<String,
    // String>(operation.get(CONFIG_PROPERTIES.getName()).asList().size());
    //            for (ModelNode property : operation.get(CONFIG_PROPERTIES.getName()).asList()) {
    //                configProperties.put(property.asProperty().getName(),
    // property.asProperty().getValue().asString());
    //            }
    //        }
    String className = getStringIfSetOrGetDefault(operation, CLASS_NAME.getName(), null);
    String jndiName = getStringIfSetOrGetDefault(operation, JNDINAME.getName(), null);
    String poolName = getStringIfSetOrGetDefault(operation, POOL_NAME.getName(), null);
    boolean enabled = getBooleanIfSetOrGetDefault(operation, ENABLED.getName(), Defaults.ENABLED);
    boolean useJavaContext =
        getBooleanIfSetOrGetDefault(
            operation, USE_JAVA_CONTEXT.getName(), Defaults.USE_JAVA_CONTEXT);
    boolean useCcm = getBooleanIfSetOrGetDefault(operation, USE_CCM.getName(), Defaults.USE_CCM);

    Integer maxPoolSize =
        getIntIfSetOrGetDefault(operation, MAX_POOL_SIZE.getName(), Defaults.MAX_POOL_SIZE);
    Integer minPoolSize =
        getIntIfSetOrGetDefault(operation, MIN_POOL_SIZE.getName(), Defaults.MIN_POOL_SIZE);
    boolean prefill =
        getBooleanIfSetOrGetDefault(operation, POOL_PREFILL.getName(), Defaults.PREFILL);
    boolean useStrictMin =
        getBooleanIfSetOrGetDefault(
            operation, POOL_USE_STRICT_MIN.getName(), Defaults.USE_STRICT_MIN);
    final FlushStrategy flushStrategy =
        operation.hasDefined(POOL_FLUSH_STRATEGY.getName())
            ? FlushStrategy.forName(operation.get(POOL_FLUSH_STRATEGY.getName()).asString())
            : Defaults.FLUSH_STRATEGY;

    Integer allocationRetry = getIntIfSetOrGetDefault(operation, ALLOCATION_RETRY.getName(), null);
    Long allocationRetryWaitMillis =
        getLongIfSetOrGetDefault(operation, ALLOCATION_RETRY_WAIT_MILLIS.getName(), null);
    Long blockingTimeoutMillis =
        getLongIfSetOrGetDefault(operation, BLOCKING_TIMEOUT_WAIT_MILLIS.getName(), null);
    Long idleTimeoutMinutes =
        getLongIfSetOrGetDefault(operation, IDLETIMEOUTMINUTES.getName(), null);
    Integer xaResourceTimeout =
        getIntIfSetOrGetDefault(operation, XA_RESOURCE_TIMEOUT.getName(), null);
    CommonTimeOut timeOut =
        new CommonTimeOutImpl(
            blockingTimeoutMillis,
            idleTimeoutMinutes,
            allocationRetry,
            allocationRetryWaitMillis,
            xaResourceTimeout);
    CommonPool pool =
        new CommonPoolImpl(minPoolSize, maxPoolSize, prefill, useStrictMin, flushStrategy);

    String securityDomain = getStringIfSetOrGetDefault(operation, SECURITY_DOMAIN.getName(), null);
    String securityDomainAndApplication =
        getStringIfSetOrGetDefault(operation, SECURITY_DOMAIN_AND_APPLICATION.getName(), null);
    Boolean application = getBooleanIfSetOrGetDefault(operation, APPLICATION.getName(), null);

    CommonSecurity security = null;

    if (securityDomain != null && securityDomainAndApplication != null && application != null) {
      if (application == null) application = Defaults.APPLICATION_MANAGED_SECURITY;
      security = new CommonSecurityImpl(securityDomain, securityDomainAndApplication, application);
    }

    Long backgroundValidationMillis =
        getLongIfSetOrGetDefault(operation, BACKGROUNDVALIDATIONMILLIS.getName(), null);
    boolean backgroundValidation =
        getBooleanIfSetOrGetDefault(
            operation, BACKGROUNDVALIDATION.getName(), Defaults.BACKGROUND_VALIDATION);
    boolean useFastFail =
        getBooleanIfSetOrGetDefault(operation, USE_FAST_FAIL.getName(), Defaults.USE_FAST_FAIl);
    CommonValidation validation =
        new CommonValidationImpl(backgroundValidation, backgroundValidationMillis, useFastFail);
    final String recoveryUsername =
        getStringIfSetOrGetDefault(operation, RECOVERY_USERNAME.getName(), null);
    String recoveryPassword =
        getStringIfSetOrGetDefault(operation, RECOVERY_PASSWORD.getName(), null);

    if (VaultUtil.isVaultFormat(recoveryPassword)) {
      try {
        recoveryPassword = VaultUtil.getValueAsString(recoveryPassword);
      } catch (SecurityVaultException e) {
        throw new RuntimeException(e); // TODO: use bundle from IJ
      }
    }
    final String recoverySecurityDomain =
        getStringIfSetOrGetDefault(operation, RECOVERY_SECURITY_DOMAIN.getName(), null);

    final Credential credential =
        new CredentialImpl(recoveryUsername, recoveryPassword, recoverySecurityDomain);

    final Extension recoverPlugin =
        extractExtension(
            operation, RECOVERLUGIN_CLASSNAME.getName(), RECOVERLUGIN_PROPERTIES.getName());
    final boolean noRecovery = getBooleanIfSetOrGetDefault(operation, NO_RECOVERY.getName(), false);
    Recovery recovery = new Recovery(credential, recoverPlugin, noRecovery);
    ModifiableConnDef connectionDefinition =
        new ModifiableConnDef(
            configProperties,
            className,
            jndiName,
            poolName,
            enabled,
            useJavaContext,
            useCcm,
            pool,
            timeOut,
            validation,
            security,
            recovery);

    return connectionDefinition;
  }
  static ModifiableXaDataSource xaFrom(
      final OperationContext operationContext, final ModelNode dataSourceNode, final String dsName)
      throws OperationFailedException, ValidateException {
    final Map<String, String> xaDataSourceProperty;
    xaDataSourceProperty = Collections.emptyMap();

    final String xaDataSourceClass =
        getStringIfSetOrGetDefault(dataSourceNode, XADATASOURCECLASS, null);
    final String jndiName = getStringIfSetOrGetDefault(dataSourceNode, JNDINAME, null);
    final String module = getStringIfSetOrGetDefault(dataSourceNode, DATASOURCE_DRIVER, null);
    final String newConnectionSql =
        getStringIfSetOrGetDefault(dataSourceNode, NEW_CONNECTION_SQL, null);
    final String poolName = dsName;
    final String urlDelimiter = getStringIfSetOrGetDefault(dataSourceNode, URL_DELIMITER, null);
    final String urlSelectorStrategyClassName =
        getStringIfSetOrGetDefault(dataSourceNode, URL_SELECTOR_STRATEGY_CLASS_NAME, null);
    final Boolean useJavaContext =
        getBooleanIfSetOrGetDefault(dataSourceNode, USE_JAVA_CONTEXT, Defaults.USE_JAVA_CONTEXT);
    final Boolean enabled = getBooleanIfSetOrGetDefault(dataSourceNode, ENABLED, Defaults.ENABLED);
    final Integer maxPoolSize =
        getIntIfSetOrGetDefault(dataSourceNode, MAX_POOL_SIZE, Defaults.MAX_POOL_SIZE);
    final Integer minPoolSize =
        getIntIfSetOrGetDefault(dataSourceNode, MIN_POOL_SIZE, Defaults.MIN_POOL_SIZE);
    final Boolean prefill =
        getBooleanIfSetOrGetDefault(dataSourceNode, POOL_PREFILL, Defaults.PREFILL);
    final Boolean useStrictMin =
        getBooleanIfSetOrGetDefault(dataSourceNode, POOL_USE_STRICT_MIN, Defaults.USE_STRICT_MIN);
    final Boolean interleaving =
        getBooleanIfSetOrGetDefault(dataSourceNode, INTERLEAVING, Defaults.INTERLEAVING);
    final Boolean noTxSeparatePool =
        getBooleanIfSetOrGetDefault(dataSourceNode, NOTXSEPARATEPOOL, Defaults.NO_TX_SEPARATE_POOL);
    final Boolean padXid = getBooleanIfSetOrGetDefault(dataSourceNode, PAD_XID, Defaults.PAD_XID);
    final Boolean isSameRmOverride =
        getBooleanIfSetOrGetDefault(dataSourceNode, SAME_RM_OVERRIDE, Defaults.IS_SAME_RM_OVERRIDE);
    final Boolean wrapXaDataSource =
        getBooleanIfSetOrGetDefault(dataSourceNode, WRAP_XA_RESOURCE, Defaults.WRAP_XA_RESOURCE);
    final FlushStrategy flushStrategy =
        dataSourceNode.hasDefined(POOL_FLUSH_STRATEGY.getName())
            ? FlushStrategy.forName(dataSourceNode.get(POOL_FLUSH_STRATEGY.getName()).asString())
            : Defaults.FLUSH_STRATEGY;

    final CommonXaPool xaPool =
        new CommonXaPoolImpl(
            minPoolSize,
            maxPoolSize,
            prefill,
            useStrictMin,
            flushStrategy,
            isSameRmOverride,
            interleaving,
            padXid,
            wrapXaDataSource,
            noTxSeparatePool);

    final String username = getStringIfSetOrGetDefault(dataSourceNode, USERNAME, null);
    final String password =
        getResolvedStringIfSetOrGetDefault(operationContext, dataSourceNode, PASSWORD, null);
    final String securityDomain = getStringIfSetOrGetDefault(dataSourceNode, SECURITY_DOMAIN, null);

    final Extension reauthPlugin =
        extractExtension(dataSourceNode, REAUTHPLUGIN_CLASSNAME, REAUTHPLUGIN_PROPERTIES);

    final DsSecurity security =
        new DsSecurityImpl(username, password, securityDomain, reauthPlugin);

    final Boolean sharePreparedStatements =
        dataSourceNode.hasDefined(SHAREPREPAREDSTATEMENTS.getName())
            ? dataSourceNode.get(SHAREPREPAREDSTATEMENTS.getName()).asBoolean()
            : Defaults.SHARE_PREPARED_STATEMENTS;
    final Long preparedStatementsCacheSize =
        getLongIfSetOrGetDefault(dataSourceNode, PREPAREDSTATEMENTSCACHESIZE, null);
    final Statement.TrackStatementsEnum trackStatements =
        dataSourceNode.hasDefined(TRACKSTATEMENTS.getName())
            ? Statement.TrackStatementsEnum.valueOf(
                dataSourceNode.get(TRACKSTATEMENTS.getName()).asString())
            : Defaults.TRACK_STATEMENTS;
    final Statement statement =
        new StatementImpl(sharePreparedStatements, preparedStatementsCacheSize, trackStatements);

    final Integer allocationRetry = getIntIfSetOrGetDefault(dataSourceNode, ALLOCATION_RETRY, null);
    final Long allocationRetryWaitMillis =
        getLongIfSetOrGetDefault(dataSourceNode, ALLOCATION_RETRY_WAIT_MILLIS, null);
    final Long blockingTimeoutMillis =
        getLongIfSetOrGetDefault(dataSourceNode, BLOCKING_TIMEOUT_WAIT_MILLIS, null);
    final Long idleTimeoutMinutes =
        getLongIfSetOrGetDefault(dataSourceNode, IDLETIMEOUTMINUTES, null);
    final Long queryTimeout = getLongIfSetOrGetDefault(dataSourceNode, QUERYTIMEOUT, null);
    final Integer xaResourceTimeout =
        getIntIfSetOrGetDefault(dataSourceNode, XA_RESOURCE_TIMEOUT, null);
    final Long useTryLock = getLongIfSetOrGetDefault(dataSourceNode, USETRYLOCK, null);
    final Boolean setTxQuertTimeout =
        getBooleanIfSetOrGetDefault(
            dataSourceNode, SETTXQUERYTIMEOUT, Defaults.SET_TX_QUERY_TIMEOUT);
    final TimeOut timeOut =
        new TimeOutImpl(
            blockingTimeoutMillis,
            idleTimeoutMinutes,
            allocationRetry,
            allocationRetryWaitMillis,
            xaResourceTimeout,
            setTxQuertTimeout,
            queryTimeout,
            useTryLock);
    final TransactionIsolation transactionIsolation =
        dataSourceNode.hasDefined(TRANSACTION_ISOLATION.getName())
            ? TransactionIsolation.valueOf(
                dataSourceNode.get(TRANSACTION_ISOLATION.getName()).asString())
            : null;
    final String checkValidConnectionSql =
        getStringIfSetOrGetDefault(dataSourceNode, CHECKVALIDCONNECTIONSQL, null);

    final Extension exceptionSorter =
        extractExtension(dataSourceNode, EXCEPTIONSORTERCLASSNAME, EXCEPTIONSORTER_PROPERTIES);
    final Extension staleConnectionChecker =
        extractExtension(
            dataSourceNode, STALECONNECTIONCHECKERCLASSNAME, STALECONNECTIONCHECKER_PROPERTIES);
    final Extension validConnectionChecker =
        extractExtension(
            dataSourceNode, VALIDCONNECTIONCHECKERCLASSNAME, VALIDCONNECTIONCHECKER_PROPERTIES);

    Long backgroundValidationMillis =
        getLongIfSetOrGetDefault(dataSourceNode, BACKGROUNDVALIDATIONMILLIS, null);
    final Boolean backgroundValidation =
        getBooleanIfSetOrGetDefault(
            dataSourceNode, BACKGROUNDVALIDATION, Defaults.BACKGROUND_VALIDATION);
    boolean useFastFail =
        getBooleanIfSetOrGetDefault(dataSourceNode, USE_FAST_FAIL, Defaults.USE_FAST_FAIl);
    final Boolean validateOnMatch =
        getBooleanIfSetOrGetDefault(dataSourceNode, VALIDATEONMATCH, Defaults.VALIDATE_ON_MATCH);
    final Boolean spy = getBooleanIfSetOrGetDefault(dataSourceNode, SPY, Defaults.SPY);
    final Boolean useCcm = getBooleanIfSetOrGetDefault(dataSourceNode, USE_CCM, Defaults.USE_CCM);
    final Validation validation =
        new ValidationImpl(
            backgroundValidation,
            backgroundValidationMillis,
            useFastFail,
            validConnectionChecker,
            checkValidConnectionSql,
            validateOnMatch,
            staleConnectionChecker,
            exceptionSorter);

    final String recoveryUsername =
        getStringIfSetOrGetDefault(dataSourceNode, RECOVERY_USERNAME, null);
    final String recoveryPassword =
        getResolvedStringIfSetOrGetDefault(
            operationContext, dataSourceNode, RECOVERY_PASSWORD, null);
    final String recoverySecurityDomain =
        getStringIfSetOrGetDefault(dataSourceNode, RECOVERY_SECURITY_DOMAIN, null);
    final Boolean noRecovery = getBooleanIfSetOrGetDefault(dataSourceNode, NO_RECOVERY, null);

    Recovery recovery = null;
    if (recoveryUsername != null
        || recoveryPassword != null
        || recoverySecurityDomain != null
        || (noRecovery != null && noRecovery.booleanValue())) {
      final Credential credential =
          new CredentialImpl(recoveryUsername, recoveryPassword, recoverySecurityDomain);
      final Extension recoverPlugin =
          extractExtension(dataSourceNode, RECOVERLUGIN_CLASSNAME, RECOVERLUGIN_PROPERTIES);

      recovery = new Recovery(credential, recoverPlugin, noRecovery);
    }
    return new ModifiableXaDataSource(
        transactionIsolation,
        timeOut,
        security,
        statement,
        validation,
        urlDelimiter,
        urlSelectorStrategyClassName,
        useJavaContext,
        poolName,
        enabled,
        jndiName,
        spy,
        useCcm,
        xaDataSourceProperty,
        xaDataSourceClass,
        module,
        newConnectionSql,
        xaPool,
        recovery);
  }
  private List<CommonConnDef> buildConnectionDefinitionObject(ModelNode parentNode)
      throws ValidateException {
    List<CommonConnDef> connDefs = new ArrayList<CommonConnDef>();
    if (parentNode.hasDefined(CONNECTIONDEFINITIONS)) {
      for (ModelNode conDefNode : parentNode.get(CONNECTIONDEFINITIONS).asList()) {
        Map<String, String> configProperties = null;
        if (conDefNode.hasDefined(CONFIG_PROPERTIES)) {
          configProperties =
              new HashMap<String, String>(conDefNode.get(CONFIG_PROPERTIES).asList().size());
          for (ModelNode property : conDefNode.get(CONFIG_PROPERTIES).asList()) {
            configProperties.put(property.asProperty().getName(), property.asString());
          }
        }
        String className = getStringIfSetOrGetDefault(conDefNode, CLASS_NAME, null);
        String jndiName = getStringIfSetOrGetDefault(conDefNode, JNDI_NAME, null);
        String poolName = getStringIfSetOrGetDefault(conDefNode, POOL_NAME, null);
        boolean enabled = getBooleanIfSetOrGetDefault(conDefNode, ENABLED, false);
        boolean useJavaContext = getBooleanIfSetOrGetDefault(conDefNode, USE_JAVA_CONTEXT, false);
        boolean useCcm = getBooleanIfSetOrGetDefault(conDefNode, USE_CCM, true);

        Integer maxPoolSize = getIntIfSetOrGetDefault(conDefNode, MAX_POOL_SIZE, null);
        Integer minPoolSize = getIntIfSetOrGetDefault(conDefNode, MIN_POOL_SIZE, null);
        boolean prefill = getBooleanIfSetOrGetDefault(conDefNode, POOL_PREFILL, false);
        boolean useStrictMin = getBooleanIfSetOrGetDefault(conDefNode, POOL_USE_STRICT_MIN, false);
        final FlushStrategy flushStrategy =
            conDefNode.hasDefined(FLUSH_STRATEGY)
                ? FlushStrategy.valueOf(conDefNode.get(FLUSH_STRATEGY).asString())
                : FlushStrategy.FAILING_CONNECTION_ONLY;

        Integer allocationRetry = getIntIfSetOrGetDefault(conDefNode, ALLOCATION_RETRY, null);
        Long allocationRetryWaitMillis =
            getLongIfSetOrGetDefault(conDefNode, ALLOCATION_RETRY_WAIT_MILLIS, null);
        Long blockingTimeoutMillis =
            getLongIfSetOrGetDefault(conDefNode, BLOCKING_TIMEOUT_WAIT_MILLIS, null);
        Long idleTimeoutMinutes = getLongIfSetOrGetDefault(conDefNode, IDLETIMEOUTMINUTES, null);
        Integer xaResourceTimeout = getIntIfSetOrGetDefault(conDefNode, XA_RESOURCE_TIMEOUT, null);
        CommonTimeOut timeOut =
            new CommonTimeOutImpl(
                blockingTimeoutMillis,
                idleTimeoutMinutes,
                allocationRetry,
                allocationRetryWaitMillis,
                xaResourceTimeout);
        CommonPool pool =
            new CommonPoolImpl(minPoolSize, maxPoolSize, prefill, useStrictMin, flushStrategy);

        String securityDomain = getStringIfSetOrGetDefault(conDefNode, SECURITY_DOMAIN, null);
        String securityDomainAndApplication =
            getStringIfSetOrGetDefault(conDefNode, SECURITY_DOMAIN_AND_APPLICATION, null);
        boolean application = getBooleanIfSetOrGetDefault(conDefNode, APPLICATION, true);
        CommonSecurity security =
            new CommonSecurityImpl(securityDomain, securityDomainAndApplication, application);

        Long backgroundValidationMillis =
            getLongIfSetOrGetDefault(conDefNode, BACKGROUNDVALIDATIONMINUTES_REMOVE, null);
        backgroundValidationMillis =
            getLongIfSetOrGetDefault(conDefNode, BACKGROUNDVALIDATIONMILLIS, null);
        boolean backgroundValidation =
            getBooleanIfSetOrGetDefault(conDefNode, BACKGROUNDVALIDATION, false);
        boolean useFastFail = getBooleanIfSetOrGetDefault(conDefNode, USE_FAST_FAIL_REMOVE, false);
        useFastFail = getBooleanIfSetOrGetDefault(conDefNode, USE_FAST_FAIL, false);
        CommonValidation validation =
            new CommonValidationImpl(backgroundValidation, backgroundValidationMillis, useFastFail);
        final String recoveryUsername =
            getStringIfSetOrGetDefault(conDefNode, RECOVERY_USERNAME, null);
        final String recoveryPassword =
            getStringIfSetOrGetDefault(conDefNode, RECOVERY_PASSWORD, null);
        final String recoverySecurityDomain =
            getStringIfSetOrGetDefault(conDefNode, RECOVERY_SECURITY_DOMAIN, null);

        final Credential credential =
            new CredentialImpl(recoveryUsername, recoveryPassword, recoverySecurityDomain);

        final Extension recoverPlugin =
            extractExtension(conDefNode, RECOVERLUGIN_CLASSNAME, RECOVERLUGIN_PROPERTIES);
        final boolean noRecovery = getBooleanIfSetOrGetDefault(conDefNode, NO_RECOVERY, false);
        Recovery recovery = new Recovery(credential, recoverPlugin, noRecovery);
        CommonConnDef connectionDefinition =
            new CommonConnDefImpl(
                configProperties,
                className,
                jndiName,
                poolName,
                enabled,
                useJavaContext,
                useCcm,
                pool,
                timeOut,
                validation,
                security,
                recovery);

        connDefs.add(connectionDefinition);
      }
    }
    return connDefs;
  }
  static ModifiableDataSource from(
      final OperationContext operationContext, final ModelNode dataSourceNode, final String dsName)
      throws OperationFailedException, ValidateException {
    final Map<String, String> connectionProperties = Collections.emptyMap();

    final String connectionUrl = getStringIfSetOrGetDefault(dataSourceNode, CONNECTION_URL, null);
    final String driverClass = getStringIfSetOrGetDefault(dataSourceNode, DRIVER_CLASS, null);
    final String dataSourceClass =
        getStringIfSetOrGetDefault(dataSourceNode, DATASOURCE_CLASS, null);
    final String jndiName = getStringIfSetOrGetDefault(dataSourceNode, JNDINAME, null);
    final String driver = getStringIfSetOrGetDefault(dataSourceNode, DATASOURCE_DRIVER, null);
    final String newConnectionSql =
        getStringIfSetOrGetDefault(dataSourceNode, NEW_CONNECTION_SQL, null);
    final String poolName = dsName;
    final String urlDelimiter = getStringIfSetOrGetDefault(dataSourceNode, URL_DELIMITER, null);
    final String urlSelectorStrategyClassName =
        getStringIfSetOrGetDefault(dataSourceNode, URL_SELECTOR_STRATEGY_CLASS_NAME, null);
    final boolean useJavaContext =
        getBooleanIfSetOrGetDefault(dataSourceNode, USE_JAVA_CONTEXT, Defaults.USE_JAVA_CONTEXT);
    final boolean enabled = getBooleanIfSetOrGetDefault(dataSourceNode, ENABLED, Defaults.ENABLED);
    final boolean jta = getBooleanIfSetOrGetDefault(dataSourceNode, JTA, Defaults.JTA);
    final Integer maxPoolSize =
        getIntIfSetOrGetDefault(dataSourceNode, MAX_POOL_SIZE, Defaults.MAX_POOL_SIZE);
    final Integer minPoolSize =
        getIntIfSetOrGetDefault(dataSourceNode, MIN_POOL_SIZE, Defaults.MIN_POOL_SIZE);
    final boolean prefill =
        getBooleanIfSetOrGetDefault(dataSourceNode, POOL_PREFILL, Defaults.PREFILL);
    final boolean useStrictMin =
        getBooleanIfSetOrGetDefault(dataSourceNode, POOL_USE_STRICT_MIN, Defaults.USE_STRICT_MIN);
    final FlushStrategy flushStrategy =
        dataSourceNode.hasDefined(POOL_FLUSH_STRATEGY.getName())
            ? FlushStrategy.forName(dataSourceNode.get(POOL_FLUSH_STRATEGY.getName()).asString())
            : Defaults.FLUSH_STRATEGY;

    final CommonPool pool =
        new CommonPoolImpl(minPoolSize, maxPoolSize, prefill, useStrictMin, flushStrategy);

    final String username = getStringIfSetOrGetDefault(dataSourceNode, USERNAME, null);

    final String password =
        getResolvedStringIfSetOrGetDefault(operationContext, dataSourceNode, PASSWORD, null);
    final String securityDomain = getStringIfSetOrGetDefault(dataSourceNode, SECURITY_DOMAIN, null);

    final Extension reauthPlugin =
        extractExtension(dataSourceNode, REAUTHPLUGIN_CLASSNAME, REAUTHPLUGIN_PROPERTIES);

    final DsSecurity security =
        new DsSecurityImpl(username, password, securityDomain, reauthPlugin);

    final boolean sharePreparedStatements =
        getBooleanIfSetOrGetDefault(
            dataSourceNode, SHAREPREPAREDSTATEMENTS, Defaults.SHARE_PREPARED_STATEMENTS);
    final Long preparedStatementsCacheSize =
        getLongIfSetOrGetDefault(dataSourceNode, PREPAREDSTATEMENTSCACHESIZE, null);
    final Statement.TrackStatementsEnum trackStatements =
        dataSourceNode.hasDefined(TRACKSTATEMENTS.getName())
            ? Statement.TrackStatementsEnum.valueOf(
                dataSourceNode.get(TRACKSTATEMENTS.getName()).asString())
            : Defaults.TRACK_STATEMENTS;
    final Statement statement =
        new StatementImpl(sharePreparedStatements, preparedStatementsCacheSize, trackStatements);

    final Integer allocationRetry = getIntIfSetOrGetDefault(dataSourceNode, ALLOCATION_RETRY, null);
    final Long allocationRetryWaitMillis =
        getLongIfSetOrGetDefault(dataSourceNode, ALLOCATION_RETRY_WAIT_MILLIS, null);
    final Long blockingTimeoutMillis =
        getLongIfSetOrGetDefault(dataSourceNode, BLOCKING_TIMEOUT_WAIT_MILLIS, null);
    final Long idleTimeoutMinutes =
        getLongIfSetOrGetDefault(dataSourceNode, IDLETIMEOUTMINUTES, null);
    final Long queryTimeout = getLongIfSetOrGetDefault(dataSourceNode, QUERYTIMEOUT, null);
    final Integer xaResourceTimeout =
        getIntIfSetOrGetDefault(dataSourceNode, XA_RESOURCE_TIMEOUT, null);
    final Long useTryLock = getLongIfSetOrGetDefault(dataSourceNode, USETRYLOCK, null);
    final boolean setTxQuertTimeout =
        getBooleanIfSetOrGetDefault(
            dataSourceNode, SETTXQUERYTIMEOUT, Defaults.SET_TX_QUERY_TIMEOUT);
    final TimeOut timeOut =
        new TimeOutImpl(
            blockingTimeoutMillis,
            idleTimeoutMinutes,
            allocationRetry,
            allocationRetryWaitMillis,
            xaResourceTimeout,
            setTxQuertTimeout,
            queryTimeout,
            useTryLock);
    final TransactionIsolation transactionIsolation =
        dataSourceNode.hasDefined(TRANSACTION_ISOLATION.getName())
            ? TransactionIsolation.valueOf(
                dataSourceNode.get(TRANSACTION_ISOLATION.getName()).asString())
            : null;
    final String checkValidConnectionSql =
        getStringIfSetOrGetDefault(dataSourceNode, CHECKVALIDCONNECTIONSQL, null);

    final Extension exceptionSorter =
        extractExtension(dataSourceNode, EXCEPTIONSORTERCLASSNAME, EXCEPTIONSORTER_PROPERTIES);
    final Extension staleConnectionChecker =
        extractExtension(
            dataSourceNode, STALECONNECTIONCHECKERCLASSNAME, STALECONNECTIONCHECKER_PROPERTIES);
    final Extension validConnectionChecker =
        extractExtension(
            dataSourceNode, VALIDCONNECTIONCHECKERCLASSNAME, VALIDCONNECTIONCHECKER_PROPERTIES);

    Long backgroundValidationMillis =
        getLongIfSetOrGetDefault(dataSourceNode, BACKGROUNDVALIDATIONMILLIS, null);
    final boolean backgroundValidation =
        getBooleanIfSetOrGetDefault(
            dataSourceNode, BACKGROUNDVALIDATION, Defaults.BACKGROUND_VALIDATION);
    boolean useFastFail =
        getBooleanIfSetOrGetDefault(dataSourceNode, USE_FAST_FAIL, Defaults.USE_FAST_FAIl);
    final boolean validateOnMatch =
        getBooleanIfSetOrGetDefault(dataSourceNode, VALIDATEONMATCH, Defaults.VALIDATE_ON_MATCH);
    final boolean spy = getBooleanIfSetOrGetDefault(dataSourceNode, SPY, Defaults.SPY);
    final boolean useCcm = getBooleanIfSetOrGetDefault(dataSourceNode, USE_CCM, Defaults.USE_CCM);

    final Validation validation =
        new ValidationImpl(
            backgroundValidation,
            backgroundValidationMillis,
            useFastFail,
            validConnectionChecker,
            checkValidConnectionSql,
            validateOnMatch,
            staleConnectionChecker,
            exceptionSorter);

    return new ModifiableDataSource(
        connectionUrl,
        driverClass,
        dataSourceClass,
        driver,
        transactionIsolation,
        connectionProperties,
        timeOut,
        security,
        statement,
        validation,
        urlDelimiter,
        urlSelectorStrategyClassName,
        newConnectionSql,
        useJavaContext,
        poolName,
        enabled,
        jndiName,
        spy,
        useCcm,
        jta,
        pool);
  }