<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002-2009 Oracle.  All rights reserved.
 *
 * $Id$
 */

package com.sleepycat.persist.model;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import com.sleepycat.db.DatabaseException;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.SecondaryIndex; // for javadoc
import com.sleepycat.persist.StoreConfig;

/**
 * Indicates a secondary key field of an entity class.  The value of the
 * secondary key field is a unique or non-unique identifier for the entity and
 * is accessed via a {@link SecondaryIndex}.
 *
 * &lt;p&gt;{@code SecondaryKey} may appear on any number of fields in an entity
 * class, subclasses and superclasses.  For a secondary key field in the entity
 * class or one of its superclasses, all entity instances will be indexed by
 * that field (if it is non-null).  For a secondary key field in an entity
 * subclass, only instances of that subclass will be indexed by that field (if
 * it is non-null).&lt;/p&gt;
 *
 * &lt;p&gt;If a secondary key field is null, the entity will not be indexed by that
 * key.  In other words, the entity cannot be queried by that secondary key nor
 * can the entity be found by iterating through the secondary index.&lt;/p&gt;
 *
 * &lt;p&gt;For a given entity class and its superclasses and subclasses, no two
 * secondary keys may have the same name.  By default, the field name
 * identifies the secondary key and the secondary index for a given entity
 * class.  {@link #name} may be specified to override this default.&lt;/p&gt;
 *
 * &lt;p&gt;Using {@link #relate}, instances of the entity class are related to
 * secondary keys in a many-to-one, one-to-many, many-to-many, or one-to-one
 * relationship.  This required property specifies the &lt;em&gt;cardinality&lt;/em&gt; of
 * each side of the relationship.&lt;/p&gt;
 *
 * &lt;p&gt;A secondary key may optionally be used to form a relationship with
 * instances of another entity class using {@link #relatedEntity} and {@link
 * #onRelatedEntityDelete}.  This establishes &lt;em&gt;foreign key constraints&lt;/em&gt;
 * for the secondary key.&lt;/p&gt;
 *
 * &lt;p&gt;The secondary key field type must be an array or collection type when a
 * &lt;em&gt;x-to-many&lt;/em&gt; relationship is used or a singular type when an
 * &lt;em&gt;x-to-one&lt;/em&gt; relationship is used; see {@link #relate}.&lt;/p&gt;
 *
 * &lt;p&gt;The field type (or element type, when an array or collection type is
 * used) of a secondary key field must follow the same rules as for a {@link
 * &lt;a href="PrimaryKey.html#keyTypes"&gt;primary key type&lt;/a&gt;}.  The {@link &lt;a
 * href="PrimaryKey.html#sortOrder"&gt;key sort order&lt;/a&gt;} is also the same.&lt;/p&gt;
 *
 * &lt;p&gt;For a secondary key field with a collection type, a type parameter must
 * be used to specify the element type.  For example {@code Collection&lt;String&gt;}
 * is allowed but {@code Collection} is not.&lt;/p&gt;
 *
 * @author Mark Hayes
 */
@Documented @Retention(RUNTIME) @Target(FIELD)
public @interface SecondaryKey {

    /**
     * Defines the relationship between instances of the entity class and the
     * secondary keys.
     *
     * &lt;p&gt;The table below summarizes how to create all four variations of
     * relationships.&lt;/p&gt;
     * &lt;div&gt;
     * &lt;table border="yes"&gt;
     *     &lt;tr&gt;&lt;th&gt;Relationship&lt;/th&gt;
     *         &lt;th&gt;Field type&lt;/th&gt;
     *         &lt;th&gt;Key type&lt;/th&gt;
     *         &lt;th&gt;Example&lt;/th&gt;
     *     &lt;/tr&gt;
     *     &lt;tr&gt;&lt;td&gt;{@link Relationship#ONE_TO_ONE}&lt;/td&gt;
     *         &lt;td&gt;Singular&lt;/td&gt;
     *         &lt;td&gt;Unique&lt;/td&gt;
     *         &lt;td&gt;A person record with a unique social security number
     *             key.&lt;/td&gt;
     *     &lt;/tr&gt;
     *     &lt;tr&gt;&lt;td&gt;{@link Relationship#MANY_TO_ONE}&lt;/td&gt;
     *         &lt;td&gt;Singular&lt;/td&gt;
     *         &lt;td&gt;Duplicates&lt;/td&gt;
     *         &lt;td&gt;A person record with a non-unique employer key.&lt;/td&gt;
     *     &lt;/tr&gt;
     *     &lt;tr&gt;&lt;td&gt;{@link Relationship#ONE_TO_MANY}&lt;/td&gt;
     *         &lt;td&gt;Array/Collection&lt;/td&gt;
     *         &lt;td&gt;Unique&lt;/td&gt;
     *         &lt;td&gt;A person record with multiple unique email address keys.&lt;/td&gt;
     *     &lt;/tr&gt;
     *     &lt;tr&gt;&lt;td&gt;{@link Relationship#MANY_TO_MANY}&lt;/td&gt;
     *         &lt;td&gt;Array/Collection&lt;/td&gt;
     *         &lt;td&gt;Duplicates&lt;/td&gt;
     *         &lt;td&gt;A person record with multiple non-unique organization
     *             keys.&lt;/td&gt;
     *     &lt;/tr&gt;
     * &lt;/table&gt;
     * &lt;/div&gt;
     *
     * &lt;p&gt;For a &lt;em&gt;many-to-x&lt;/em&gt; relationship, the secondary index will
     * have non-unique keys; in other words, duplicates will be allowed.
     * Conversely, for &lt;em&gt;one-to-x&lt;/em&gt; relationship, the secondary index
     * will have unique keys.&lt;/p&gt;
     *
     * &lt;p&gt;For a &lt;em&gt;x-to-one&lt;/em&gt; relationship, the secondary key field is
     * singular; in other words, it may not be an array or collection type.
     * Conversely, for a &lt;em&gt;x-to-many&lt;/em&gt; relationship, the secondary key
     * field must be an array or collection type.  A collection type is any
     * implementation of {@link java.util.Collection}.&lt;/p&gt;
     */
    Relationship relate();

    /**
     * Specifies the entity to which this entity is related, for establishing
     * foreign key constraints.  Values of this secondary key will be
     * constrained to the set of primary key values for the given entity class.
     *
     * &lt;p&gt;The given class must be an entity class.  This class is called the
     * &lt;em&gt;related entity&lt;/em&gt; or &lt;em&gt;foreign entity&lt;/em&gt;.&lt;/p&gt;
     *
     * &lt;p&gt;When a related entity class is specified, a check (foreign key
     * constraint) is made every time a new secondary key value is stored for
     * this entity, and every time a related entity is deleted.&lt;/p&gt;
     *
     * &lt;p&gt;Whenever a new secondary key value is stored for this entity, it is
     * checked to ensure it exists as a primary key value of the related
     * entity.  If it does not, a {@link DatabaseException} will be thrown
     * by the {@link PrimaryIndex} {@code put} method.&lt;/p&gt;
     *
     * &lt;p&gt;Whenever a related entity is deleted and its primary key value exists
     * as a secondary key value for this entity, the action is taken that is
     * specified using the {@link #onRelatedEntityDelete} property.&lt;/p&gt;
     *
     * &lt;p&gt;Together, these two checks guarantee that a secondary key value for
     * this entity will always exist as a primary key value for the related
     * entity.  Note, however, that a transactional store must be configured
     * to guarantee this to be true in the face of a crash; see {@link
     * StoreConfig#setTransactional}.&lt;/p&gt;
     */
    Class relatedEntity() default void.class;

    /**
     * Specifies the action to take when a related entity is deleted having a
     * primary key value that exists as a secondary key value for this entity.
     *
     * &lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; This property only applies when {@link #relatedEntity}
     * is specified to define the related entity.&lt;/p&gt;
     *
     * &lt;p&gt;The default action, {@link DeleteAction#ABORT ABORT}, means that a
     * {@link DatabaseException} is thrown in order to abort the current
     * transaction.&lt;/p&gt;
     *
     * &lt;p&gt;If {@link DeleteAction#CASCADE CASCADE} is specified, then this
     * entity will be deleted also.  This in turn could trigger further
     * deletions, causing a cascading effect.&lt;/p&gt;
     *
     * &lt;p&gt;If {@link DeleteAction#NULLIFY NULLIFY} is specified, then the
     * secondary key in this entity is set to null and this entity is updated.
     * If the key field type is singular, the field value is set to null;
     * therefore, to specify {@code NULLIFY} for a singular key field type, a
     * primitive wrapper type must be used instead of a primitive type.  If the
     * key field type is an array or collection type, the key is deleted from
     * the array (the array is resized) or from the collection (using {@link
     * java.util.Collection#remove Collection.remove}).&lt;/p&gt;
     */
    DeleteAction onRelatedEntityDelete() default DeleteAction.ABORT;

    /**
     * Specifies the name of the key in order to use a name that is different
     * than the field name.
     *
     * &lt;p&gt;This is convenient when prefixes or suffices are used on field names.
     * For example:&lt;/p&gt;
     * &lt;pre class="code"&gt;
     *  class Person {
     *      {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class, name="parentSsn")}
     *      String m_parentSsn;
     *  }&lt;/pre&gt;
     *
     * &lt;p&gt;It can also be used to uniquely name a key when multiple secondary
     * keys for a single entity class have the same field name.  For example,
     * an entity class and its subclass may both have a field named 'date',
     * and both fields are used as secondary keys.  The {@code name} property
     * can be specified for one or both fields to give each key a unique
     * name.&lt;/p&gt;
     */
    String name() default "";
}
</pre></body></html>