@Override
  public ConnectionProvider initiateService(
      Map configurationValues, ServiceRegistryImplementor registry) {
    if (MultiTenancyStrategy.determineMultiTenancyStrategy(configurationValues)
        != MultiTenancyStrategy.NONE) {
      // nothing to do, but given the separate hierarchies have to handle this here.
    }

    final ClassLoaderService classLoaderService = registry.getService(ClassLoaderService.class);

    ConnectionProvider connectionProvider = null;
    String providerClassName = getConfiguredConnectionProviderName(configurationValues);
    if (providerClassName != null) {
      connectionProvider =
          instantiateExplicitConnectionProvider(providerClassName, classLoaderService);
    } else if (configurationValues.get(Environment.DATASOURCE) != null) {
      connectionProvider = new DatasourceConnectionProviderImpl();
    }

    if (connectionProvider == null) {
      if (c3p0ConfigDefined(configurationValues) && c3p0ProviderPresent(classLoaderService)) {
        connectionProvider =
            instantiateExplicitConnectionProvider(C3P0_PROVIDER_CLASS_NAME, classLoaderService);
      }
    }

    if (connectionProvider == null) {
      if (proxoolConfigDefined(configurationValues) && proxoolProviderPresent(classLoaderService)) {
        connectionProvider =
            instantiateExplicitConnectionProvider(PROXOOL_PROVIDER_CLASS_NAME, classLoaderService);
      }
    }

    if (connectionProvider == null) {
      if (configurationValues.get(Environment.URL) != null) {
        connectionProvider = new DriverManagerConnectionProviderImpl();
      }
    }

    if (connectionProvider == null) {
      LOG.noAppropriateConnectionProvider();
      connectionProvider = new UserSuppliedConnectionProviderImpl();
    }

    final Map injectionData = (Map) configurationValues.get(INJECTION_DATA);
    if (injectionData != null && injectionData.size() > 0) {
      final ConnectionProvider theConnectionProvider = connectionProvider;
      new BeanInfoHelper(connectionProvider.getClass())
          .applyToBeanInfo(
              connectionProvider,
              new BeanInfoHelper.BeanInfoDelegate() {
                public void processBeanInfo(BeanInfo beanInfo) throws Exception {
                  PropertyDescriptor[] descritors = beanInfo.getPropertyDescriptors();
                  for (int i = 0, size = descritors.length; i < size; i++) {
                    String propertyName = descritors[i].getName();
                    if (injectionData.containsKey(propertyName)) {
                      Method method = descritors[i].getWriteMethod();
                      method.invoke(theConnectionProvider, injectionData.get(propertyName));
                    }
                  }
                }
              });
    }

    return connectionProvider;
  }
    public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) {
      this.serviceRegistry = serviceRegistry;

      final StrategySelector strategySelector = serviceRegistry.getService(StrategySelector.class);
      final ConfigurationService configService =
          serviceRegistry.getService(ConfigurationService.class);

      this.mappingDefaults = new MappingDefaultsImpl(serviceRegistry);

      //			jandexView = (IndexView) configService.getSettings().get( AvailableSettings.JANDEX_INDEX
      // );

      scanOptions =
          new StandardScanOptions(
              (String) configService.getSettings().get(AvailableSettings.SCANNER_DISCOVERY), false);
      // ScanEnvironment must be set explicitly
      scannerSetting = configService.getSettings().get(AvailableSettings.SCANNER);
      if (scannerSetting == null) {
        scannerSetting = configService.getSettings().get(AvailableSettings.SCANNER_DEPRECATED);
        if (scannerSetting != null) {
          DEPRECATION_LOGGER.logDeprecatedScannerSetting();
        }
      }
      archiveDescriptorFactory =
          strategySelector.resolveStrategy(
              ArchiveDescriptorFactory.class,
              configService.getSettings().get(AvailableSettings.SCANNER_ARCHIVE_INTERPRETER));

      multiTenancyStrategy =
          MultiTenancyStrategy.determineMultiTenancyStrategy(configService.getSettings());

      implicitDiscriminatorsForJoinedInheritanceSupported =
          configService.getSetting(
              AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS,
              StandardConverters.BOOLEAN,
              false);

      explicitDiscriminatorsForJoinedInheritanceSupported =
          !configService.getSetting(
              AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS,
              StandardConverters.BOOLEAN,
              false);

      implicitlyForceDiscriminatorInSelect =
          configService.getSetting(
              AvailableSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT,
              StandardConverters.BOOLEAN,
              false);

      sharedCacheMode =
          configService.getSetting(
              "javax.persistence.sharedCache.mode",
              new ConfigurationService.Converter<SharedCacheMode>() {
                @Override
                public SharedCacheMode convert(Object value) {
                  if (value == null) {
                    return null;
                  }

                  if (SharedCacheMode.class.isInstance(value)) {
                    return (SharedCacheMode) value;
                  }

                  return SharedCacheMode.valueOf(value.toString());
                }
              },
              SharedCacheMode.UNSPECIFIED);

      defaultCacheAccessType =
          configService.getSetting(
              AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY,
              new ConfigurationService.Converter<AccessType>() {
                @Override
                public AccessType convert(Object value) {
                  if (value == null) {
                    return null;
                  }

                  if (CacheConcurrencyStrategy.class.isInstance(value)) {
                    return ((CacheConcurrencyStrategy) value).toAccessType();
                  }

                  if (AccessType.class.isInstance(value)) {
                    return (AccessType) value;
                  }

                  return AccessType.fromExternalName(value.toString());
                }
              },
              // by default, see if the defined RegionFactory (if one) defines a default
              serviceRegistry.getService(RegionFactory.class) == null
                  ? null
                  : serviceRegistry.getService(RegionFactory.class).getDefaultAccessType());

      specjProprietarySyntaxEnabled =
          configService.getSetting(
              "hibernate.enable_specj_proprietary_syntax", StandardConverters.BOOLEAN, false);

      implicitNamingStrategy =
          strategySelector.resolveDefaultableStrategy(
              ImplicitNamingStrategy.class,
              configService.getSettings().get(AvailableSettings.IMPLICIT_NAMING_STRATEGY),
              ImplicitNamingStrategyLegacyJpaImpl.INSTANCE);

      physicalNamingStrategy =
          strategySelector.resolveDefaultableStrategy(
              PhysicalNamingStrategy.class,
              configService.getSettings().get(AvailableSettings.PHYSICAL_NAMING_STRATEGY),
              PhysicalNamingStrategyStandardImpl.INSTANCE);

      sourceProcessOrdering = resolveInitialSourceProcessOrdering(configService);

      final boolean useNewIdentifierGenerators =
          configService.getSetting(
              AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, StandardConverters.BOOLEAN, false);
      if (useNewIdentifierGenerators) {
        idGenerationTypeInterpreter.disableLegacyFallback();
      } else {
        idGenerationTypeInterpreter.enableLegacyFallback();
      }

      reflectionManager = generateDefaultReflectionManager();
    }
  public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) {
    final boolean debugEnabled = LOG.isDebugEnabled();
    final JdbcServices jdbcServices = serviceRegistry.getService(JdbcServices.class);
    Settings settings = new Settings();

    // SessionFactory name:

    String sessionFactoryName = props.getProperty(AvailableSettings.SESSION_FACTORY_NAME);
    settings.setSessionFactoryName(sessionFactoryName);
    settings.setSessionFactoryNameAlsoJndiName(
        ConfigurationHelper.getBoolean(
            AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, props, true));

    // JDBC and connection settings:

    // Interrogate JDBC metadata
    ExtractedDatabaseMetaData meta = jdbcServices.getExtractedMetaDataSupport();

    settings.setDataDefinitionImplicitCommit(meta.doesDataDefinitionCauseTransactionCommit());
    settings.setDataDefinitionInTransactionSupported(meta.supportsDataDefinitionInTransaction());

    // use dialect default properties
    final Properties properties = new Properties();
    properties.putAll(jdbcServices.getDialect().getDefaultProperties());
    properties.putAll(props);

    // Transaction settings:
    settings.setJtaPlatform(serviceRegistry.getService(JtaPlatform.class));

    MultiTableBulkIdStrategy multiTableBulkIdStrategy =
        serviceRegistry
            .getService(StrategySelector.class)
            .resolveStrategy(
                MultiTableBulkIdStrategy.class,
                properties.getProperty(AvailableSettings.HQL_BULK_ID_STRATEGY));
    if (multiTableBulkIdStrategy == null) {
      multiTableBulkIdStrategy =
          jdbcServices.getDialect().supportsTemporaryTables()
              ? TemporaryTableBulkIdStrategy.INSTANCE
              : new PersistentTableBulkIdStrategy();
    }
    settings.setMultiTableBulkIdStrategy(multiTableBulkIdStrategy);

    boolean flushBeforeCompletion =
        ConfigurationHelper.getBoolean(AvailableSettings.FLUSH_BEFORE_COMPLETION, properties);
    if (debugEnabled) {
      LOG.debugf(
          "Automatic flush during beforeCompletion(): %s", enabledDisabled(flushBeforeCompletion));
    }
    settings.setFlushBeforeCompletionEnabled(flushBeforeCompletion);

    boolean autoCloseSession =
        ConfigurationHelper.getBoolean(AvailableSettings.AUTO_CLOSE_SESSION, properties);
    if (debugEnabled) {
      LOG.debugf(
          "Automatic session close at end of transaction: %s", enabledDisabled(autoCloseSession));
    }
    settings.setAutoCloseSessionEnabled(autoCloseSession);

    // JDBC and connection settings:

    int batchSize =
        ConfigurationHelper.getInt(AvailableSettings.STATEMENT_BATCH_SIZE, properties, 0);
    if (!meta.supportsBatchUpdates()) {
      batchSize = 0;
    }
    if (batchSize > 0 && debugEnabled) {
      LOG.debugf("JDBC batch size: %s", batchSize);
    }
    settings.setJdbcBatchSize(batchSize);

    boolean jdbcBatchVersionedData =
        ConfigurationHelper.getBoolean(AvailableSettings.BATCH_VERSIONED_DATA, properties, false);
    if (batchSize > 0 && debugEnabled) {
      LOG.debugf(
          "JDBC batch updates for versioned data: %s", enabledDisabled(jdbcBatchVersionedData));
    }
    settings.setJdbcBatchVersionedData(jdbcBatchVersionedData);

    boolean useScrollableResultSets =
        ConfigurationHelper.getBoolean(
            AvailableSettings.USE_SCROLLABLE_RESULTSET,
            properties,
            meta.supportsScrollableResults());
    if (debugEnabled) {
      LOG.debugf("Scrollable result sets: %s", enabledDisabled(useScrollableResultSets));
    }
    settings.setScrollableResultSetsEnabled(useScrollableResultSets);

    boolean wrapResultSets =
        ConfigurationHelper.getBoolean(AvailableSettings.WRAP_RESULT_SETS, properties, false);
    if (debugEnabled) {
      LOG.debugf("Wrap result sets: %s", enabledDisabled(wrapResultSets));
    }
    settings.setWrapResultSetsEnabled(wrapResultSets);

    boolean useGetGeneratedKeys =
        ConfigurationHelper.getBoolean(
            AvailableSettings.USE_GET_GENERATED_KEYS, properties, meta.supportsGetGeneratedKeys());
    if (debugEnabled) {
      LOG.debugf("JDBC3 getGeneratedKeys(): %s", enabledDisabled(useGetGeneratedKeys));
    }
    settings.setGetGeneratedKeysEnabled(useGetGeneratedKeys);

    Integer statementFetchSize =
        ConfigurationHelper.getInteger(AvailableSettings.STATEMENT_FETCH_SIZE, properties);
    if (statementFetchSize != null && debugEnabled) {
      LOG.debugf("JDBC result set fetch size: %s", statementFetchSize);
    }
    settings.setJdbcFetchSize(statementFetchSize);

    MultiTenancyStrategy multiTenancyStrategy =
        MultiTenancyStrategy.determineMultiTenancyStrategy(properties);
    if (debugEnabled) {
      LOG.debugf("multi-tenancy strategy : %s", multiTenancyStrategy);
    }
    settings.setMultiTenancyStrategy(multiTenancyStrategy);

    String releaseModeName =
        ConfigurationHelper.getString(AvailableSettings.RELEASE_CONNECTIONS, properties, "auto");
    if (debugEnabled) {
      LOG.debugf("Connection release mode: %s", releaseModeName);
    }
    ConnectionReleaseMode releaseMode;
    if ("auto".equals(releaseModeName)) {
      releaseMode = serviceRegistry.getService(TransactionFactory.class).getDefaultReleaseMode();
    } else {
      releaseMode = ConnectionReleaseMode.parse(releaseModeName);
      if (releaseMode == ConnectionReleaseMode.AFTER_STATEMENT) {
        // we need to make sure the underlying JDBC connection access supports aggressive release...
        boolean supportsAgrressiveRelease =
            multiTenancyStrategy.requiresMultiTenantConnectionProvider()
                ? serviceRegistry
                    .getService(MultiTenantConnectionProvider.class)
                    .supportsAggressiveRelease()
                : serviceRegistry.getService(ConnectionProvider.class).supportsAggressiveRelease();
        if (!supportsAgrressiveRelease) {
          LOG.unsupportedAfterStatement();
          releaseMode = ConnectionReleaseMode.AFTER_TRANSACTION;
        }
      }
    }
    settings.setConnectionReleaseMode(releaseMode);

    final BatchFetchStyle batchFetchStyle =
        BatchFetchStyle.interpret(properties.get(AvailableSettings.BATCH_FETCH_STYLE));
    LOG.debugf("Using BatchFetchStyle : " + batchFetchStyle.name());
    settings.setBatchFetchStyle(batchFetchStyle);

    // SQL Generation settings:

    String defaultSchema = properties.getProperty(AvailableSettings.DEFAULT_SCHEMA);
    String defaultCatalog = properties.getProperty(AvailableSettings.DEFAULT_CATALOG);
    if (defaultSchema != null && debugEnabled) {
      LOG.debugf("Default schema: %s", defaultSchema);
    }
    if (defaultCatalog != null && debugEnabled) {
      LOG.debugf("Default catalog: %s", defaultCatalog);
    }
    settings.setDefaultSchemaName(defaultSchema);
    settings.setDefaultCatalogName(defaultCatalog);

    Integer maxFetchDepth =
        ConfigurationHelper.getInteger(AvailableSettings.MAX_FETCH_DEPTH, properties);
    if (maxFetchDepth != null) {
      LOG.debugf("Maximum outer join fetch depth: %s", maxFetchDepth);
    }
    settings.setMaximumFetchDepth(maxFetchDepth);

    int batchFetchSize =
        ConfigurationHelper.getInt(AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, properties, 1);
    if (debugEnabled) {
      LOG.debugf("Default batch fetch size: %s", batchFetchSize);
    }
    settings.setDefaultBatchFetchSize(batchFetchSize);

    boolean comments =
        ConfigurationHelper.getBoolean(AvailableSettings.USE_SQL_COMMENTS, properties);
    if (debugEnabled) {
      LOG.debugf("Generate SQL with comments: %s", enabledDisabled(comments));
    }
    settings.setCommentsEnabled(comments);

    boolean orderUpdates =
        ConfigurationHelper.getBoolean(AvailableSettings.ORDER_UPDATES, properties);
    if (debugEnabled) {
      LOG.debugf("Order SQL updates by primary key: %s", enabledDisabled(orderUpdates));
    }
    settings.setOrderUpdatesEnabled(orderUpdates);

    boolean orderInserts =
        ConfigurationHelper.getBoolean(AvailableSettings.ORDER_INSERTS, properties);
    if (debugEnabled) {
      LOG.debugf("Order SQL inserts for batching: %s", enabledDisabled(orderInserts));
    }
    settings.setOrderInsertsEnabled(orderInserts);

    String defaultNullPrecedence =
        ConfigurationHelper.getString(
            AvailableSettings.DEFAULT_NULL_ORDERING, properties, "none", "first", "last");
    if (debugEnabled) {
      LOG.debugf("Default null ordering: %s", defaultNullPrecedence);
    }
    settings.setDefaultNullPrecedence(NullPrecedence.parse(defaultNullPrecedence));

    // Query parser settings:

    settings.setQueryTranslatorFactory(createQueryTranslatorFactory(properties, serviceRegistry));

    Map querySubstitutions =
        ConfigurationHelper.toMap(
            AvailableSettings.QUERY_SUBSTITUTIONS, " ,=;:\n\t\r\f", properties);
    if (debugEnabled) {
      LOG.debugf("Query language substitutions: %s", querySubstitutions);
    }
    settings.setQuerySubstitutions(querySubstitutions);

    boolean jpaqlCompliance =
        ConfigurationHelper.getBoolean(
            AvailableSettings.JPAQL_STRICT_COMPLIANCE, properties, false);
    if (debugEnabled) {
      LOG.debugf("JPA-QL strict compliance: %s", enabledDisabled(jpaqlCompliance));
    }
    settings.setStrictJPAQLCompliance(jpaqlCompliance);

    // Second-level / query cache:

    boolean useSecondLevelCache =
        ConfigurationHelper.getBoolean(AvailableSettings.USE_SECOND_LEVEL_CACHE, properties, true);
    if (debugEnabled) {
      LOG.debugf("Second-level cache: %s", enabledDisabled(useSecondLevelCache));
    }
    settings.setSecondLevelCacheEnabled(useSecondLevelCache);

    boolean useQueryCache =
        ConfigurationHelper.getBoolean(AvailableSettings.USE_QUERY_CACHE, properties);
    if (debugEnabled) {
      LOG.debugf("Query cache: %s", enabledDisabled(useQueryCache));
    }
    settings.setQueryCacheEnabled(useQueryCache);
    if (useQueryCache) {
      settings.setQueryCacheFactory(createQueryCacheFactory(properties, serviceRegistry));
    }

    // The cache provider is needed when we either have second-level cache enabled
    // or query cache enabled.  Note that useSecondLevelCache is enabled by default
    settings.setRegionFactory(
        createRegionFactory(properties, (useSecondLevelCache || useQueryCache), serviceRegistry));

    boolean useMinimalPuts =
        ConfigurationHelper.getBoolean(
            AvailableSettings.USE_MINIMAL_PUTS,
            properties,
            settings.getRegionFactory().isMinimalPutsEnabledByDefault());
    if (debugEnabled) {
      LOG.debugf("Optimize cache for minimal puts: %s", enabledDisabled(useMinimalPuts));
    }
    settings.setMinimalPutsEnabled(useMinimalPuts);

    String prefix = properties.getProperty(AvailableSettings.CACHE_REGION_PREFIX);
    if (StringHelper.isEmpty(prefix)) {
      prefix = null;
    }
    if (prefix != null && debugEnabled) {
      LOG.debugf("Cache region prefix: %s", prefix);
    }
    settings.setCacheRegionPrefix(prefix);

    boolean useStructuredCacheEntries =
        ConfigurationHelper.getBoolean(AvailableSettings.USE_STRUCTURED_CACHE, properties, false);
    if (debugEnabled) {
      LOG.debugf(
          "Structured second-level cache entries: %s", enabledDisabled(useStructuredCacheEntries));
    }
    settings.setStructuredCacheEntriesEnabled(useStructuredCacheEntries);

    boolean useDirectReferenceCacheEntries =
        ConfigurationHelper.getBoolean(
            AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES, properties, false);
    if (debugEnabled) {
      LOG.debugf(
          "Second-level cache direct-reference entries: %s",
          enabledDisabled(useDirectReferenceCacheEntries));
    }
    settings.setDirectReferenceCacheEntriesEnabled(useDirectReferenceCacheEntries);

    // Statistics and logging:

    boolean useStatistics =
        ConfigurationHelper.getBoolean(AvailableSettings.GENERATE_STATISTICS, properties);
    if (debugEnabled) {
      LOG.debugf("Statistics: %s", enabledDisabled(useStatistics));
    }
    settings.setStatisticsEnabled(useStatistics);

    boolean useIdentifierRollback =
        ConfigurationHelper.getBoolean(AvailableSettings.USE_IDENTIFIER_ROLLBACK, properties);
    if (debugEnabled) {
      LOG.debugf(
          "Deleted entity synthetic identifier rollback: %s",
          enabledDisabled(useIdentifierRollback));
    }
    settings.setIdentifierRollbackEnabled(useIdentifierRollback);

    // Schema export:

    String autoSchemaExport = properties.getProperty(AvailableSettings.HBM2DDL_AUTO);
    if ("validate".equals(autoSchemaExport)) {
      settings.setAutoValidateSchema(true);
    }
    if ("update".equals(autoSchemaExport)) {
      settings.setAutoUpdateSchema(true);
    }
    if ("create".equals(autoSchemaExport)) {
      settings.setAutoCreateSchema(true);
    }
    if ("create-drop".equals(autoSchemaExport)) {
      settings.setAutoCreateSchema(true);
      settings.setAutoDropSchema(true);
    }
    settings.setImportFiles(properties.getProperty(AvailableSettings.HBM2DDL_IMPORT_FILES));

    EntityMode defaultEntityMode =
        EntityMode.parse(properties.getProperty(AvailableSettings.DEFAULT_ENTITY_MODE));
    if (debugEnabled) {
      LOG.debugf("Default entity-mode: %s", defaultEntityMode);
    }
    settings.setDefaultEntityMode(defaultEntityMode);

    boolean namedQueryChecking =
        ConfigurationHelper.getBoolean(AvailableSettings.QUERY_STARTUP_CHECKING, properties, true);
    if (debugEnabled) {
      LOG.debugf("Named query checking : %s", enabledDisabled(namedQueryChecking));
    }
    settings.setNamedQueryStartupCheckingEnabled(namedQueryChecking);

    boolean checkNullability =
        ConfigurationHelper.getBoolean(AvailableSettings.CHECK_NULLABILITY, properties, true);
    if (debugEnabled) {
      LOG.debugf(
          "Check Nullability in Core (should be disabled when Bean Validation is on): %s",
          enabledDisabled(checkNullability));
    }
    settings.setCheckNullability(checkNullability);

    // TODO: Does EntityTuplizerFactory really need to be configurable? revisit for HHH-6383
    settings.setEntityTuplizerFactory(new EntityTuplizerFactory());

    //		String provider = properties.getProperty( AvailableSettings.BYTECODE_PROVIDER );
    //		log.info( "Bytecode provider name : " + provider );
    //		BytecodeProvider bytecodeProvider = buildBytecodeProvider( provider );
    //		settings.setBytecodeProvider( bytecodeProvider );

    boolean initializeLazyStateOutsideTransactionsEnabled =
        ConfigurationHelper.getBoolean(
            AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, properties, false);
    if (debugEnabled) {
      LOG.debugf(
          "Allow initialization of lazy state outside session : : %s",
          enabledDisabled(initializeLazyStateOutsideTransactionsEnabled));
    }
    settings.setInitializeLazyStateOutsideTransactions(
        initializeLazyStateOutsideTransactionsEnabled);

    return settings;
  }