1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: Accessor.java,v 1.1 2008/02/07 17:12:27 mark Exp $
7 */
8
9package com.sleepycat.persist.impl;
10
11/**
12 * Field binding operations implemented via reflection (ReflectionAccessor) or
13 * bytecode enhancement (EnhancedAccessor).
14 *
15 * <p>Normally we read the set of all secondary key fields first and then the
16 * set of all non-key fields, reading each set in order of field name.  But
17 * when reading an old format record we must account for the following
18 * class evolution conversions:</p>
19 * <ul>
20 * <li>Convert a field: pass value thru converter</li>
21 * <li>Widen a field type: pass value thru widener</li>
22 * <li>Add a field: don't read the new field</li>
23 * <li>Delete a field: skip the deleted field</li>
24 * <li>Rename a field: read field in a different order</li>
25 * </ul>
26 * <p>To support these operations, the methods for reading fields allow reading
27 * specific ranges of fields as well as all fields.  For example, all fields
28 * up to a deleted field could be read, and then all fields from the following
29 * field onward.</p>
30 *
31 * @author Mark Hayes
32 */
33interface Accessor {
34
35    /**
36     * A large field value to use instead of Integer.MAX_VALUE, to work around
37     * Java JIT compiler bug when doing an (X <= Integer.MAX_VALUE) as would be
38     * done in readXxxKeyFields methods.
39     */
40    final int MAX_FIELD_NUM = Integer.MAX_VALUE - 1;
41
42    /**
43     * Creates a new instance of the target class using its default
44     * constructor.
45     */
46    Object newInstance();
47
48    /**
49     * Creates a new one dimensional array of the given length, having the
50     * target class as its component type.
51     *
52     * <p>Using a special method for a one dimensional array, which can be
53     * implemented by bytecode generation, is a compromise.  We use reflection
54     * to create multidimensional arrays.  We could in the future generate code
55     * to create arrays as they are encountered, if there is a need to avoid
56     * reflection for multidimensional arrays.</p>
57     */
58    Object newArray(int len);
59
60    /**
61     * Returns whether the primary key field is null (for a reference type) or
62     * zero (for a primitive integer type).  Null and zero are used as an
63     * indication that the key should be assigned from a sequence.
64     */
65    boolean isPriKeyFieldNullOrZero(Object o);
66
67    /**
68     * Writes the primary key field value to the given EntityOutput.
69     *
70     * <p>To write a primary key with a reference type, this method must call
71     * EntityOutput.writeKeyObject.</p>
72     *
73     * @param o is the object whose primary key field is to be written.
74     *
75     * @param output the output data to write to.
76     */
77    void writePriKeyField(Object o, EntityOutput output);
78
79    /**
80     * Reads the primary key field value from the given EntityInput.
81     *
82     * <p>To read a primary key with a reference type, this method must call
83     * EntityInput.readKeyObject.</p>
84     *
85     * @param o is the object whose primary key field is to be read.
86     *
87     * @param input the input data to read from.
88     */
89    void readPriKeyField(Object o, EntityInput input);
90
91    /**
92     * Writes all secondary key field values to the given EntityOutput,
93     * writing fields in super classes first and in name order within class.
94     *
95     * @param o is the object whose secondary key fields are to be written.
96     *
97     * <p>If the primary key has a reference type, this method must call
98     * EntityOutput.registerPriKeyObject before writing any other fields.</p>
99     *
100     * @param output the output data to write to.
101     */
102    void writeSecKeyFields(Object o, EntityOutput output);
103
104    /**
105     * Reads a range of secondary key field values from the given EntityInput,
106     * reading fields in super classes first and in name order within class.
107     *
108     * <p>If the primary key has a reference type, this method must call
109     * EntityInput.registerPriKeyObject before reading any other fields.</p>
110     *
111     * <p>To read all fields, pass -1 for superLevel, zero for startField and
112     * MAX_FIELD_NUM for endField.  Fields from super classes are read
113     * first.</p>
114     *
115     * <p>To read a specific range of fields, pass a non-negative number for
116     * superLevel and the specific indices of the field range to be read in the
117     * class at that level.</p>
118     *
119     * @param o is the object whose secondary key fields are to be read.
120     *
121     * @param input the input data to read from.
122     *
123     * @param startField the starting field index in the range of fields to
124     * read.  To read all fields, the startField should be zero.
125     *
126     * @param endField the ending field index in the range of fields to read.
127     * To read all fields, the endField should be MAX_FIELD_NUM.
128     *
129     * @param superLevel is a non-negative number to read the fields of the
130     * class that is the Nth super instance; or a negative number to read
131     * fields in all classes.
132     */
133    void readSecKeyFields(Object o,
134                          EntityInput input,
135                          int startField,
136                          int endField,
137                          int superLevel);
138
139    /**
140     * Writes all non-key field values to the given EntityOutput, writing
141     * fields in super classes first and in name order within class.
142     *
143     * @param o is the object whose non-key fields are to be written.
144     *
145     * @param output the output data to write to.
146     */
147    void writeNonKeyFields(Object o, EntityOutput output);
148
149    /**
150     * Reads a range of non-key field values from the given EntityInput,
151     * reading fields in super classes first and in name order within class.
152     *
153     * <p>To read all fields, pass -1 for superLevel, zero for startField and
154     * MAX_FIELD_NUM for endField.  Fields from super classes are read
155     * first.</p>
156     *
157     * <p>To read a specific range of fields, pass a non-negative number for
158     * superLevel and the specific indices of the field range to be read in the
159     * class at that level.</p>
160     *
161     * @param o is the object whose non-key fields are to be read.
162     *
163     * @param input the input data to read from.
164     *
165     * @param startField the starting field index in the range of fields to
166     * read.  To read all fields, the startField should be zero.
167     *
168     * @param endField the ending field index in the range of fields to read.
169     * To read all fields, the endField should be MAX_FIELD_NUM.
170     *
171     * @param superLevel is a non-negative number to read the fields of the
172     * class that is the Nth super instance; or a negative number to read
173     * fields in all classes.
174     */
175    void readNonKeyFields(Object o,
176                          EntityInput input,
177                          int startField,
178                          int endField,
179                          int superLevel);
180
181    /**
182     * Returns the value of a given field, representing primitives as primitive
183     * wrapper objects.
184     *
185     * @param o is the object containing the key field.
186     *
187     * @param field is the field index.
188     *
189     * @param superLevel is a positive number to identify the field of the
190     * class that is the Nth super instance; or zero to identify the field in
191     * this class.
192     *
193     * @param isSecField is true for a secondary key field or false for a
194     * non-key field.
195     *
196     * @return the current field value, or null for a reference type field
197     * that is null.
198     */
199    Object getField(Object o,
200                    int field,
201                    int superLevel,
202                    boolean isSecField);
203
204    /**
205     * Changes the value of a given field, representing primitives as primitive
206     * wrapper objects.
207     *
208     * @param o is the object containing the key field.
209     *
210     * @param field is the field index.
211     *
212     * @param superLevel is a positive number to identify the field of the
213     * class that is the Nth super instance; or zero to identify the field in
214     * this class.
215     *
216     * @param isSecField is true for a secondary key field or false for a
217     * non-key field.
218     *
219     * @param value is the new value of the field, or null to set a reference
220     * type field to null.
221     */
222    void setField(Object o,
223                  int field,
224                  int superLevel,
225                  boolean isSecField,
226                  Object value);
227}
228