@Override
  public QueryParserService initiateService(
      SessionFactoryImplementor sessionFactory,
      Configuration configuration,
      ServiceRegistryImplementor registry) {
    ConfigurationPropertyReader propertyReader =
        new ConfigurationPropertyReader(
            configuration, registry.getService(ClassLoaderService.class));

    return propertyReader
        .property(InternalProperties.QUERY_PARSER_SERVICE, QueryParserService.class)
        .instantiate()
        .withDefaultImplementation(
            registry.getService(DatastoreProvider.class).getDefaultQueryParserServiceType())
        .getValue();
  }
  @Override
  public void configure(Map configurationValues) {
    ClassLoaderService classLoaderService = registry.getService(ClassLoaderService.class);
    ConfigurationPropertyReader propertyReader =
        new ConfigurationPropertyReader(configurationValues, classLoaderService);

    sessionFactoryOptions =
        new OptionsServiceContextImpl(OptionValueSources.getDefaultSources(propertyReader));
  }
  @Override
  public DatastoreProvider initiateService(
      SessionFactoryImplementor sessionFactory,
      Configuration configuration,
      ServiceRegistryImplementor registry) {
    ConfigurationPropertyReader propertyReader =
        new ConfigurationPropertyReader(
            configuration, registry.getService(ClassLoaderService.class));

    DatastoreProvider datastoreProvider =
        propertyReader
            .property(DATASTORE_PROVIDER, DatastoreProvider.class)
            .withDefaultImplementation(DEFAULT_DATASTORE_PROVIDER)
            .withShortNameResolver(DatastoreProviderShortNameResolver.INSTANCE)
            .getValue();

    log.useDatastoreProvider(datastoreProvider.getClass().getName());
    return datastoreProvider;
  }
  OgmEntityPersister(
      final PersistentClass persistentClass,
      final EntityRegionAccessStrategy cacheAccessStrategy,
      final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
      final SessionFactoryImplementor factory,
      final Mapping mapping,
      final EntityDiscriminator discriminator)
      throws HibernateException {
    super(persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory);
    if (log.isTraceEnabled()) {
      log.tracef("Creating OgmEntityPersister for %s", persistentClass.getClassName());
    }
    ServiceRegistryImplementor serviceRegistry = factory.getServiceRegistry();
    this.gridDialect = serviceRegistry.getService(GridDialect.class);
    this.optionsService = serviceRegistry.getService(OptionsService.class);

    tableName =
        persistentClass
            .getTable()
            .getQualifiedName(
                factory.getDialect(),
                factory.getSettings().getDefaultCatalogName(),
                factory.getSettings().getDefaultSchemaName());

    this.discriminator = discriminator;

    // SPACES
    // TODO: i'm not sure, but perhaps we should exclude
    //      abstract denormalized tables?

    int spacesSize = 1 + persistentClass.getSynchronizedTables().size();
    spaces = new String[spacesSize];
    spaces[0] = tableName;
    @SuppressWarnings("unchecked")
    Iterator<String> syncTablesIter = persistentClass.getSynchronizedTables().iterator();
    for (int i = 1; i < spacesSize; i++) {
      spaces[i] = syncTablesIter.next();
    }

    HashSet<String> subclassTables = new HashSet<String>();
    Iterator<Table> tableIter = persistentClass.getSubclassTableClosureIterator();
    while (tableIter.hasNext()) {
      Table table = tableIter.next();
      subclassTables.add(
          table.getQualifiedName(
              factory.getDialect(),
              factory.getSettings().getDefaultCatalogName(),
              factory.getSettings().getDefaultSchemaName()));
    }
    subclassSpaces = ArrayHelper.toStringArray(subclassTables);

    if (isMultiTable()) {
      int idColumnSpan = getIdentifierColumnSpan();
      ArrayList<String> tableNames = new ArrayList<String>();
      ArrayList<String[]> keyColumns = new ArrayList<String[]>();
      if (!isAbstract()) {
        tableNames.add(tableName);
        keyColumns.add(getIdentifierColumnNames());
      }
      @SuppressWarnings("unchecked")
      Iterator<Table> iter = persistentClass.getSubclassTableClosureIterator();
      while (iter.hasNext()) {
        Table tab = iter.next();
        if (!tab.isAbstractUnionTable()) {
          String tableName =
              tab.getQualifiedName(
                  factory.getDialect(),
                  factory.getSettings().getDefaultCatalogName(),
                  factory.getSettings().getDefaultSchemaName());
          tableNames.add(tableName);
          String[] key = new String[idColumnSpan];
          @SuppressWarnings("unchecked")
          Iterator<Column> citer = tab.getPrimaryKey().getColumnIterator();
          for (int k = 0; k < idColumnSpan; k++) {
            key[k] = citer.next().getQuotedName(factory.getDialect());
          }
          keyColumns.add(key);
        }
      }

      constraintOrderedTableNames = ArrayHelper.toStringArray(tableNames);
      constraintOrderedKeyColumnNames = ArrayHelper.to2DStringArray(keyColumns);
    } else {
      constraintOrderedTableNames = new String[] {tableName};
      constraintOrderedKeyColumnNames = new String[][] {getIdentifierColumnNames()};
    }

    initPropertyPaths(mapping);

    // Grid related metadata
    TypeTranslator typeTranslator = serviceRegistry.getService(TypeTranslator.class);
    final Type[] types = getPropertyTypes();
    final int length = types.length;
    gridPropertyTypes = new GridType[length];
    for (int index = 0; index < length; index++) {
      gridPropertyTypes[index] = typeTranslator.getType(types[index]);
    }
    gridVersionType = typeTranslator.getType(getVersionType());
    gridIdentifierType = typeTranslator.getType(getIdentifierType());
    List<String> columnNames = new ArrayList<String>();
    for (int propertyCount = 0; propertyCount < this.getPropertySpan(); propertyCount++) {
      String[] property = this.getPropertyColumnNames(propertyCount);
      for (int columnCount = 0; columnCount < property.length; columnCount++) {
        columnNames.add(property[columnCount]);
      }
    }
    if (discriminator.getColumnName() != null) {
      columnNames.add(discriminator.getColumnName());
    }
    this.tupleContext =
        new TupleContext(columnNames, optionsService.context().getEntityOptions(getMappedClass()));
    jpaEntityName = persistentClass.getJpaEntityName();
    entityKeyMetadata = new EntityKeyMetadata(getTableName(), getIdentifierColumnNames());
    // load unique key association key metadata
    associationKeyMetadataPerPropertyName = new HashMap<String, AssociationKeyMetadata>();
    initAssociationKeyMetadata();
    initCustomSQLStrings();
  }
 @Override
 public void injectServices(ServiceRegistryImplementor serviceRegistryImplementor) {
   this.jtaPlatform = serviceRegistryImplementor.getService(JtaPlatform.class);
 }
  @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;
  }