// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gwtorm.nosql;

import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SchemaModel;
import com.google.gwtorm.schema.java.JavaSchemaModel;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.Schema;
import com.google.gwtorm.server.SchemaConstructorGen;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.SchemaGen;

/**
 * Base class for NoSQL typed databases.
 *
 * <p>Applications should use the database class to create instances of their Schema extension
 * interface, and thus open and connect to the data store.
 *
 * <p>Creating a new database instance is expensive, due to the type analysis and code generation
 * performed to implement the Schema and Access interfaces. Applications should create and cache
 * their database instance for the life of the application.
 *
 * <p>Database instances are thread-safe, but returned Schema instances are not.
 *
 * <p>This class must be further extended by the NoSQL implementation to configure the connectivity
 * with the data store and supply the correct subclass of {@link NoSqlSchema} that knows how to
 * interact with the data store.
 *
 * @param <T> type of the application's Schema.
 * @param <S> type of the implementation's base for Schema implementations.
 * @param <A> type of the implementation's base for Access implementations.
 */
@SuppressWarnings("rawtypes")
public abstract class NoSqlDatabase<T extends Schema, S extends NoSqlSchema, A extends NoSqlAccess>
    implements SchemaFactory<T> {

  private final SchemaModel schemaModel;
  private final SchemaFactory<T> implFactory;

  /**
   * Initialize a new database and generate the implementation.
   *
   * @param schemaBaseType class that the generated Schema implementation should extend in order to
   *     provide data store connectivity.
   * @param accessBaseType class that the generated Access implementations should extend in order to
   *     provide single-relation access for each schema instance.
   * @param appSchema the application schema interface that must be implemented and constructed on
   *     demand.
   * @throws OrmException the schema cannot be created because of an annotation error in the
   *     interface definitions.
   */
  protected NoSqlDatabase(
      final Class<S> schemaBaseType, final Class<A> accessBaseType, final Class<T> appSchema)
      throws OrmException {
    schemaModel = new JavaSchemaModel(appSchema);
    final GeneratedClassLoader loader = newLoader(appSchema);
    final Class<T> impl = generate(schemaBaseType, accessBaseType, loader);
    implFactory = new SchemaConstructorGen<>(loader, impl, this).create();
  }

  @Override
  public T open() throws OrmException {
    return implFactory.open();
  }

  /** @return the derived model of the application's schema. */
  public SchemaModel getSchemaModel() {
    return schemaModel;
  }

  @SuppressWarnings("unchecked")
  private Class<T> generate(
      final Class<S> schemaBaseType,
      final Class<A> accessBaseType,
      final GeneratedClassLoader loader)
      throws OrmException {
    return new SchemaGen(
            loader,
            schemaModel,
            getClass(),
            schemaBaseType,
            new SchemaGen.AccessGenerator() {
              @Override
              public Class<?> create(GeneratedClassLoader loader, RelationModel rm)
                  throws OrmException {
                return new AccessGen(loader, rm, schemaBaseType, accessBaseType).create();
              }
            })
        .create();
  }

  private static <T> GeneratedClassLoader newLoader(final Class<T> schema) {
    return new GeneratedClassLoader(schema.getClassLoader());
  }
}
