summaryrefslogtreecommitdiff
path: root/lang/java/src/com/sleepycat/persist/impl/Accessor.java
blob: b41431b965853b77e95049c8ba4be88ac9913427 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 */

package com.sleepycat.persist.impl;

/**
 * Field binding operations implemented via reflection (ReflectionAccessor) or
 * bytecode enhancement (EnhancedAccessor).
 *
 * <p>Normally we read the set of all secondary key fields first and then the
 * set of all non-key fields, reading each set in order of field name.  But
 * when reading an old format record we must account for the following
 * class evolution conversions:</p>
 * <ul>
 * <li>Convert a field: pass value thru converter</li>
 * <li>Widen a field type: pass value thru widener</li>
 * <li>Add a field: don't read the new field</li>
 * <li>Delete a field: skip the deleted field</li>
 * <li>Rename a field: read field in a different order</li>
 * </ul>
 * <p>To support these operations, the methods for reading fields allow reading
 * specific ranges of fields as well as all fields.  For example, all fields
 * up to a deleted field could be read, and then all fields from the following
 * field onward.</p>
 *
 * @author Mark Hayes
 */
interface Accessor {

    /**
     * A large field value to use instead of Integer.MAX_VALUE, to work around
     * Java JIT compiler bug when doing an (X <= Integer.MAX_VALUE) as would be
     * done in readXxxKeyFields methods.
     */
    final int MAX_FIELD_NUM = Integer.MAX_VALUE - 1;

    /**
     * Creates a new instance of the target class using its default
     * constructor.
     */
    Object newInstance();

    /**
     * Creates a new one dimensional array of the given length, having the
     * target class as its component type.
     *
     * <p>Using a special method for a one dimensional array, which can be
     * implemented by bytecode generation, is a compromise.  We use reflection
     * to create multidimensional arrays.  We could in the future generate code
     * to create arrays as they are encountered, if there is a need to avoid
     * reflection for multidimensional arrays.</p>
     */
    Object newArray(int len);

    /**
     * Returns whether the primary key field is null (for a reference type) or
     * zero (for a primitive integer type).  Null and zero are used as an
     * indication that the key should be assigned from a sequence.
     */
    boolean isPriKeyFieldNullOrZero(Object o);

    /**
     * Writes the primary key field value to the given EntityOutput.
     *
     * <p>To write a primary key with a reference type, this method must call
     * EntityOutput.writeKeyObject.</p>
     *
     * @param o is the object whose primary key field is to be written.
     *
     * @param output the output data to write to.
     */
    void writePriKeyField(Object o, EntityOutput output)
        throws RefreshException;

    /**
     * Reads the primary key field value from the given EntityInput.
     *
     * <p>To read a primary key with a reference type, this method must call
     * EntityInput.readKeyObject.</p>
     *
     * @param o is the object whose primary key field is to be read.
     *
     * @param input the input data to read from.
     */
    void readPriKeyField(Object o, EntityInput input)
        throws RefreshException;

    /**
     * Writes all secondary key field values to the given EntityOutput,
     * writing fields in super classes first and in name order within class.
     *
     * @param o is the object whose secondary key fields are to be written.
     *
     * <p>If the primary key has a reference type, this method must call
     * EntityOutput.registerPriKeyObject before writing any other fields.</p>
     *
     * @param output the output data to write to.
     */
    void writeSecKeyFields(Object o, EntityOutput output)
        throws RefreshException;

    /**
     * Reads a range of secondary key field values from the given EntityInput,
     * reading fields in super classes first and in name order within class.
     *
     * <p>If the primary key has a reference type, this method must call
     * EntityInput.registerPriKeyObject before reading any other fields.</p>
     *
     * <p>To read all fields, pass -1 for superLevel, zero for startField and
     * MAX_FIELD_NUM for endField.  Fields from super classes are read
     * first.</p>
     *
     * <p>To read a specific range of fields, pass a non-negative number for
     * superLevel and the specific indices of the field range to be read in the
     * class at that level.</p>
     *
     * @param o is the object whose secondary key fields are to be read.
     *
     * @param input the input data to read from.
     *
     * @param startField the starting field index in the range of fields to
     * read.  To read all fields, the startField should be zero.
     *
     * @param endField the ending field index in the range of fields to read.
     * To read all fields, the endField should be MAX_FIELD_NUM.
     *
     * @param superLevel is a non-negative number to read the fields of the
     * class that is the Nth super instance; or a negative number to read
     * fields in all classes.
     */
    void readSecKeyFields(Object o,
                          EntityInput input,
                          int startField,
                          int endField,
                          int superLevel)
        throws RefreshException;

    /**
     * Writes all non-key field values to the given EntityOutput, writing
     * fields in super classes first and in name order within class.
     *
     * @param o is the object whose non-key fields are to be written.
     *
     * @param output the output data to write to.
     */
    void writeNonKeyFields(Object o, EntityOutput output)
        throws RefreshException;

    /**
     * Reads a range of non-key field values from the given EntityInput,
     * reading fields in super classes first and in name order within class.
     *
     * <p>To read all fields, pass -1 for superLevel, zero for startField and
     * MAX_FIELD_NUM for endField.  Fields from super classes are read
     * first.</p>
     *
     * <p>To read a specific range of fields, pass a non-negative number for
     * superLevel and the specific indices of the field range to be read in the
     * class at that level.</p>
     *
     * @param o is the object whose non-key fields are to be read.
     *
     * @param input the input data to read from.
     *
     * @param startField the starting field index in the range of fields to
     * read.  To read all fields, the startField should be zero.
     *
     * @param endField the ending field index in the range of fields to read.
     * To read all fields, the endField should be MAX_FIELD_NUM.
     *
     * @param superLevel is a non-negative number to read the fields of the
     * class that is the Nth super instance; or a negative number to read
     * fields in all classes.
     */
    void readNonKeyFields(Object o,
                          EntityInput input,
                          int startField,
                          int endField,
                          int superLevel)
        throws RefreshException;

    /**
     * Writes all composite key field values to the given EntityOutput, writing
     * in declared field number order.
     *
     * @param o the composite key object whose fields are to be written.
     *
     * @param output the output data to write to.
     */
    void writeCompositeKeyFields(Object o, EntityOutput output)
        throws RefreshException;

    /**
     * Reads all composite key field values from the given EntityInput,
     * reading in declared field number order.
     *
     * @param o the composite key object whose fields are to be read.
     *
     * @param input the input data to read from.
     */
    void readCompositeKeyFields(Object o, EntityInput input)
        throws RefreshException;

    /**
     * Returns the value of a given field, representing primitives as primitive
     * wrapper objects.
     *
     * @param o is the object containing the key field.
     *
     * @param field is the field index.
     *
     * @param superLevel is a positive number to identify the field of the
     * class that is the Nth super instance; or zero to identify the field in
     * this class.
     *
     * @param isSecField is true for a secondary key field or false for a
     * non-key field.
     *
     * @return the current field value, or null for a reference type field
     * that is null.
     */
    Object getField(Object o,
                    int field,
                    int superLevel,
                    boolean isSecField);

    /**
     * Changes the value of a given field, representing primitives as primitive
     * wrapper objects.
     *
     * @param o is the object containing the key field.
     *
     * @param field is the field index.
     *
     * @param superLevel is a positive number to identify the field of the
     * class that is the Nth super instance; or zero to identify the field in
     * this class.
     *
     * @param isSecField is true for a secondary key field or false for a
     * non-key field.
     *
     * @param value is the new value of the field, or null to set a reference
     * type field to null.
     */
    void setField(Object o,
                  int field,
                  int superLevel,
                  boolean isSecField,
                  Object value);
    
    /**
     * Changes the value of the primary key field, representing primitives as 
     * primitive wrapper objects.
     *
     * @param o is the object containing the primary key field.
     *
     * @param field is the field index.
     *
     * @param superLevel is a positive number to identify the field of the
     * class that is the Nth super instance; or zero to identify the field in
     * this class.
     *
     * @param value is the new value of the field, or null to set a reference
     * type field to null.
     */
    void setPriField(Object o, Object value); 
}