// Copyright 2008 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.server;

import com.google.common.util.concurrent.CheckedFuture;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.Key;
import java.util.Map;

/**
 * Data access interface for an entity type.
 *
 * <p>Applications should extend this interface for each entity type they need to access. At runtime
 * the application extension will be automatically implemented with a generated class, providing
 * concrete implementations for all methods.
 *
 * <p>Instances should be acquired through the application's extension interface of {@link Schema}.
 *
 * <p>Applications should implement a query method using the {@link PrimaryKey} annotation, for
 * example:
 *
 * <pre>
 * public interface FooAccess extends Access&lt;Foo, Foo.Key&gt; {
 *   &#064;PrimaryKey(&quot;key&quot;)
 *   Foo byKey(Foo.Key k) throws OrmException;
 * }
 * </pre>
 *
 * <p>otherwise the primaryKey, get, update and delete operations declared by this interface will be
 * unsupported.
 *
 * @param <T> type of the entity. Any object type is suitable, so long as at least one field uses a
 *     {@link Column} annotation.
 * @param <K> type of the primary key of entity. If the primary key is a primitive type then use Key
 *     directly, otherwise use a Key implementation. Entity specific key subclasses are recommended.
 */
public interface Access<T extends Object, K extends Key<?>> {
  /** @return the name of this relation. */
  String getRelationName();

  /** @return the id of this relation (if defined), otherwise 0. */
  int getRelationID();

  /**
   * Iterate through all members of the relation.
   *
   * @return an iterator over all members. This is most likely not fast.
   */
  ResultSet<T> iterateAllEntities() throws OrmException;

  /**
   * Obtain the primary key of an entity instance.
   *
   * @param entity the entity to get the key of; must not be null.
   * @return the primary key. Null if this entity has no primary key declared, or if the primary key
   *     does not implement the Key interface.
   */
  K primaryKey(T entity);

  /**
   * Convert a collection of objects into a map, keyed by their primary key.
   *
   * @param c the collection
   * @return a map of the objects, indexed by their primary key.
   */
  Map<K, T> toMap(Iterable<T> c);

  /**
   * Lookup a single entity via its primary key.
   *
   * <p>This method is only implemented if the entity's primary key is defined to be an
   * implementation of the {@link Key} interface. Otherwise the method throws {@link
   * UnsupportedOperationException}.
   *
   * @param key the primary key instance; must not be null.
   * @return the entity; null if no entity has this key.
   * @throws OrmException the data lookup failed.
   * @throws UnsupportedOperationException the key type doesn't implement Key.
   */
  T get(K key) throws OrmException;

  /**
   * Lookup a single entity asynchronously via its primary key.
   *
   * <p>This method is only implemented if the entity's primary key is defined to be an
   * implementation of the {@link Key} interface. Otherwise the method throws {@link
   * UnsupportedOperationException}.
   *
   * @param key the primary key instance; must not be null.
   * @return a {@link CheckedFuture} for the entity; the {@link CheckedFuture#get()} will return
   *     null if no entity has this key.
   * @throws UnsupportedOperationException the key type doesn't implement Key.
   */
  CheckedFuture<T, OrmException> getAsync(K key);

  /**
   * Lookup multiple entities via their primary key.
   *
   * <p>This method is only implemented if the entity's primary key is defined to be an
   * implementation of the {@link Key} interface. Otherwise the method throws {@link
   * UnsupportedOperationException}.
   *
   * <p>This method is a batch form of {@link #get(Key)} and may be optimized to reduce round-trips
   * to the data store.
   *
   * @param keys collection of zero or more keys to perform lookup with.
   * @return collection of all matching entities; this may be a smaller result than the keys
   *     supplied if one or more of the keys does not match an existing entity.
   * @throws OrmException the data lookup failed.
   * @throws UnsupportedOperationException the key type doesn't implement Key.
   */
  ResultSet<T> get(Iterable<K> keys) throws OrmException;

  /**
   * Immediately insert new entities into the data store.
   *
   * @param instances the instances to insert. The iteration occurs only once.
   * @throws OrmException data insertion failed.
   */
  void insert(Iterable<T> instances) throws OrmException;

  /**
   * Immediately update existing entities in the data store.
   *
   * @param instances the instances to update. The iteration occurs only once.
   * @throws OrmException data modification failed.
   * @throws UnsupportedOperationException no PrimaryKey was declared.
   */
  void update(Iterable<T> instances) throws OrmException;

  /**
   * Immediately update or insert entities in the data store.
   *
   * @param instances the instances to update. The iteration occurs only once.
   * @throws OrmException data modification failed.
   * @throws UnsupportedOperationException no PrimaryKey was declared.
   */
  void upsert(Iterable<T> instances) throws OrmException;

  /**
   * Immediately delete existing entities from the data store.
   *
   * @param keys the keys to delete. The iteration occurs only once.
   * @throws OrmException data removal failed.
   * @throws UnsupportedOperationException no PrimaryKey was declared.
   */
  void deleteKeys(Iterable<K> keys) throws OrmException;

  /**
   * Immediately delete existing entities from the data store.
   *
   * @param instances the instances to delete. The iteration occurs only once.
   * @throws OrmException data removal failed.
   * @throws UnsupportedOperationException no PrimaryKey was declared.
   */
  void delete(Iterable<T> instances) throws OrmException;

  /**
   * Start a transaction on an object.
   *
   * @param key key describing the object (and its children).
   * @throws OrmException a transaction cannot be started.
   */
  void beginTransaction(K key) throws OrmException;

  /**
   * Atomically update a single entity.
   *
   * <p>If the entity does not exist, the method returns {@code null} without invoking {@code
   * update}.
   *
   * <p>If the entity exists, the method invokes {@code update} with a current copy of the entity.
   * The update function should edit the passed instance in-place. The return value will be returned
   * to the caller, but is otherwise ignored by this update function.
   *
   * @param key key which identifies the entity.
   * @param update the update function.
   * @return the updated copy of the entity; or {@code null}.
   * @throws OrmException data update failed.
   */
  T atomicUpdate(K key, AtomicUpdate<T> update) throws OrmException;
}
