// 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;
}
