1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: KeyField.java,v 1.1 2008/02/07 17:12:28 mark Exp $
7 */
8
9package com.sleepycat.persist.model;
10
11import static java.lang.annotation.ElementType.FIELD;
12import static java.lang.annotation.RetentionPolicy.RUNTIME;
13
14import java.lang.annotation.Documented;
15import java.lang.annotation.Retention;
16import java.lang.annotation.Target;
17
18import com.sleepycat.db.Environment;
19
20/**
21 * Indicates the sorting position of a key field in a composite key class when
22 * the {@code Comparable} interface is not implemented.  The {@code KeyField}
23 * integer value specifies the sort order of this field within the set of
24 * fields in the composite key.
25 *
26 * <p>If the field type of a {@link PrimaryKey} or {@link SecondaryKey} is a
27 * composite key class containing more than one key field, then a {@code
28 * KeyField} annotation must be present on each non-transient instance field of
29 * the composite key class.  The {@code KeyField} value must be a number
30 * between one and the number of non-transient instance fields declared in the
31 * composite key class.</p>
32 *
33 * <p>Note that a composite key class is a flat container for one or more
34 * simple type fields.  All non-transient instance fields in the composite key
35 * class are key fields, and the composite key class may not have superclasses
36 * containing non-transient instance fields.</p>
37 *
38 * <p>For example:</p>
39 * <pre class="code">
40 *  {@literal @Entity}
41 *  class Animal {
42 *      {@literal @PrimaryKey}
43 *      Classification classification;
44 *      ...
45 *  }
46 *
47 *  {@literal @Persistent}
48 *  class Classification {
49 *      {@literal @KeyField(1) String kingdom;}
50 *      {@literal @KeyField(2) String phylum;}
51 *      {@literal @KeyField(3) String clazz;}
52 *      {@literal @KeyField(4) String order;}
53 *      {@literal @KeyField(5) String family;}
54 *      {@literal @KeyField(6) String genus;}
55 *      {@literal @KeyField(7) String species;}
56 *      {@literal @KeyField(8) String subspecies;}
57 *      ...
58 *  }</pre>
59 *
60 * <p>This causes entities to be sorted first by {@code kingdom}, then by
61 * {@code phylum} within {@code kingdom}, and so on.</p>
62 *
63 * <p>The fields in a composite key class may not be null.</p>
64 *
65 * <p><a name="comparable"><strong>Custom Sort Order</strong></a></p>
66 *
67 * <p>To override the default sort order, a composite key class may implement
68 * the {@link Comparable} interface.  This allows overriding the sort order and
69 * is therefore useful even when there is only one key field in the composite
70 * key class.  For example, the following class sorts Strings using a Canadian
71 * collator:</p>
72 *
73 * <pre class="code">
74 *  import java.text.Collator;
75 *  import java.util.Locale;
76 *
77 *  {@literal @Entity}
78 *  class Animal {
79 *      ...
80 *      {@literal @SecondaryKey(relate=ONE_TO_ONE)}
81 *      CollatedString canadianName;
82 *      ...
83 *  }
84 *
85 *  {@literal @Persistent}
86 *  {@literal class CollatedString implements Comparable<CollatedString>} {
87 *
88 *      static Collator collator = Collator.getInstance(Locale.CANADA);
89 *
90 *      {@literal @KeyField(1)}
91 *      String value;
92 *
93 *      CollatedString(String value) { this.value = value; }
94 *
95 *      private CollatedString() {}
96 *
97 *      public int compareTo(CollatedString o) {
98 *          return collator.compare(value, o.value);
99 *      }
100 *  }</pre>
101 *
102 * <p>Several important rules should be considered when implementing a custom
103 * comparison method.  Failure to follow these rules may result in the primary
104 * or secondary index becoming unusable; in other words, the store will not be
105 * able to function.</p>
106 * <ol>
107 * <li>The comparison method must always return the same result, given the same
108 * inputs.  The behavior of the comparison method must not change over
109 * time.</li>
110 * <br>
111 * <li>A corollary to the first rule is that the behavior of the comparison
112 * method must not be dependent on state which may change over time.  For
113 * example, if the above collation method used the default Java locale, and the
114 * default locale is changed, then the sort order will change.</li>
115 * <br>
116 * <li>The comparison method must not assume that it is called after the store
117 * has been opened.  With Berkeley DB Java Edition, the comparison method is
118 * called during database recovery, which occurs in the {@link Environment}
119 * constructor.</li>
120 * <br>
121 * <li>The comparison method must not assume that it will only be called with
122 * keys that are currently present in the database.  The comparison method will
123 * occasionally be called with deleted keys or with keys for records that were
124 * not part of a committed transaction.</li>
125 * </ol>
126 *
127 * @author Mark Hayes
128 */
129@Documented @Retention(RUNTIME) @Target(FIELD)
130public @interface KeyField {
131
132    int value();
133}
134