1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: RawAccessor.java,v 1.1 2008/02/07 17:12:27 mark Exp $
7 */
8
9package com.sleepycat.persist.impl;
10
11import java.util.Collections;
12import java.util.HashMap;
13import java.util.List;
14
15import com.sleepycat.persist.raw.RawObject;
16
17/**
18 * Implements Accessor for RawObject access.
19 *
20 * @author Mark Hayes
21 */
22class RawAccessor implements Accessor {
23
24    private Format parentFormat;
25    private Accessor superAccessor;
26    private FieldInfo priKeyField;
27    private List<FieldInfo> secKeyFields;
28    private List<FieldInfo> nonKeyFields;
29    private boolean isCompositeKey;
30
31    RawAccessor(Format parentFormat,
32                Accessor superAccessor,
33                FieldInfo priKeyField,
34                List<FieldInfo> secKeyFields,
35                List<FieldInfo> nonKeyFields) {
36        this.parentFormat = parentFormat;
37        this.superAccessor = superAccessor;
38        this.priKeyField = priKeyField;
39        this.secKeyFields = secKeyFields;
40        this.nonKeyFields = nonKeyFields;
41    }
42
43    RawAccessor(Format parentFormat,
44                List<FieldInfo> nonKeyFields) {
45        this.parentFormat = parentFormat;
46        this.nonKeyFields = nonKeyFields;
47        secKeyFields = Collections.emptyList();
48        isCompositeKey = true;
49    }
50
51    public Object newInstance() {
52        RawObject superObject;
53        if (superAccessor != null) {
54            superObject = ((RawObject) superAccessor.newInstance());
55        } else {
56            superObject = null;
57        }
58        return new RawObject
59            (parentFormat, new HashMap<String,Object>(), superObject);
60    }
61
62    public Object newArray(int len) {
63        throw new UnsupportedOperationException();
64    }
65
66    public boolean isPriKeyFieldNullOrZero(Object o) {
67        if (priKeyField != null) {
68            Object val = getValue(o, priKeyField);
69            Format format = priKeyField.getType();
70            if (format.isPrimitive()) {
71                return ((Number) val).longValue() == 0L;
72            } else {
73                return val == null;
74            }
75        } else if (superAccessor != null) {
76            return superAccessor.isPriKeyFieldNullOrZero(getSuper(o));
77        } else {
78            throw new IllegalStateException("No primary key field");
79        }
80    }
81
82    public void writePriKeyField(Object o, EntityOutput output) {
83        if (priKeyField != null) {
84            Object val = getValue(o, priKeyField);
85            Format format = priKeyField.getType();
86            output.writeKeyObject(val, format);
87        } else if (superAccessor != null) {
88            superAccessor.writePriKeyField(getSuper(o), output);
89        } else {
90            throw new IllegalStateException("No primary key field");
91        }
92    }
93
94    public void readPriKeyField(Object o, EntityInput input) {
95        if (priKeyField != null) {
96            Format format = priKeyField.getType();
97            Object val = input.readKeyObject(format);
98            setValue(o, priKeyField, val);
99        } else if (superAccessor != null) {
100            superAccessor.readPriKeyField(getSuper(o), input);
101        } else {
102            throw new IllegalStateException("No primary key field");
103        }
104    }
105
106    public void writeSecKeyFields(Object o, EntityOutput output) {
107        if (priKeyField != null && !priKeyField.getType().isPrimitive()) {
108            output.registerPriKeyObject(getValue(o, priKeyField));
109        }
110        if (superAccessor != null) {
111            superAccessor.writeSecKeyFields(getSuper(o), output);
112        }
113        for (int i = 0; i < secKeyFields.size(); i += 1) {
114            writeField(o, secKeyFields.get(i), output);
115        }
116    }
117
118    public void readSecKeyFields(Object o,
119                                 EntityInput input,
120                                 int startField,
121                                 int endField,
122                                 int superLevel) {
123        if (priKeyField != null && !priKeyField.getType().isPrimitive()) {
124            input.registerPriKeyObject(getValue(o, priKeyField));
125        }
126        if (superLevel != 0 && superAccessor != null) {
127            superAccessor.readSecKeyFields
128                (getSuper(o), input, startField, endField, superLevel - 1);
129        } else {
130            if (superLevel > 0) {
131                throw new IllegalStateException
132                    ("Super class does not exist");
133            }
134        }
135        if (superLevel <= 0) {
136            for (int i = startField;
137                 i <= endField && i < secKeyFields.size();
138                 i += 1) {
139                readField(o, secKeyFields.get(i), input);
140            }
141        }
142    }
143
144    public void writeNonKeyFields(Object o, EntityOutput output) {
145        if (superAccessor != null) {
146            superAccessor.writeNonKeyFields(getSuper(o), output);
147        }
148        for (int i = 0; i < nonKeyFields.size(); i += 1) {
149            writeField(o, nonKeyFields.get(i), output);
150        }
151    }
152
153    public void readNonKeyFields(Object o,
154                                 EntityInput input,
155                                 int startField,
156                                 int endField,
157                                 int superLevel) {
158        if (superLevel != 0 && superAccessor != null) {
159            superAccessor.readNonKeyFields
160                (getSuper(o), input, startField, endField, superLevel - 1);
161        } else {
162            if (superLevel > 0) {
163                throw new IllegalStateException
164                    ("Super class does not exist");
165            }
166        }
167        if (superLevel <= 0) {
168            for (int i = startField;
169                 i <= endField && i < nonKeyFields.size();
170                 i += 1) {
171                readField(o, nonKeyFields.get(i), input);
172            }
173        }
174    }
175
176    public Object getField(Object o,
177                           int field,
178                           int superLevel,
179                           boolean isSecField) {
180        if (superLevel > 0) {
181            return superAccessor.getField
182                (getSuper(o), field, superLevel - 1, isSecField);
183        }
184        FieldInfo fld =
185	    isSecField ? secKeyFields.get(field) : nonKeyFields.get(field);
186        return getValue(o, fld);
187    }
188
189    public void setField(Object o,
190                         int field,
191                         int superLevel,
192                         boolean isSecField,
193                         Object value) {
194        if (superLevel > 0) {
195            superAccessor.setField
196                (getSuper(o), field, superLevel - 1, isSecField, value);
197	    return;
198        }
199        FieldInfo fld =
200	    isSecField ? secKeyFields.get(field) : nonKeyFields.get(field);
201        setValue(o, fld, value);
202    }
203
204    private RawObject getSuper(Object o) {
205        return ((RawObject) o).getSuper();
206    }
207
208    private Object getValue(Object o, FieldInfo field) {
209        return ((RawObject) o).getValues().get(field.getName());
210    }
211
212    private void setValue(Object o, FieldInfo field, Object val) {
213        ((RawObject) o).getValues().put(field.getName(), val);
214    }
215
216    private void writeField(Object o, FieldInfo field, EntityOutput output) {
217        Object val = getValue(o, field);
218        Format format = field.getType();
219        if (isCompositeKey || format.isPrimitive()) {
220            output.writeKeyObject(val, format);
221        } else {
222            output.writeObject(val, format);
223        }
224    }
225
226    private void readField(Object o, FieldInfo field, EntityInput input) {
227        Format format = field.getType();
228        Object val;
229        if (isCompositeKey || format.isPrimitive()) {
230            val = input.readKeyObject(format);
231        } else {
232            val = input.readObject();
233        }
234        setValue(o, field, val);
235    }
236}
237