1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.openjpa.kernel;
20
21 import java.util.BitSet;
22
23 import org.apache.openjpa.meta.ClassMetaData;
24 import org.apache.openjpa.meta.FieldMetaData;
25
26 /**
27 * Default {@link PCData} implementation.
28 *
29 * @author Patrick Linskey
30 * @author Abe White
31 * @nojavadoc
32 */
33 public class PCDataImpl
34 extends AbstractPCData {
35
36 private final Object _oid;
37 private final Class _type;
38 private final Object[] _data;
39 private final BitSet _loaded;
40 private Object _version = null;
41 private Object _impl = null;
42 private Object[] _fieldImpl = null;
43
44 /**
45 * Constructor.
46 */
47 public PCDataImpl(Object oid, ClassMetaData meta) {
48 _oid = oid;
49 _type = meta.getDescribedType();
50
51 int len = meta.getFields().length;
52 _data = new Object[len];
53 _loaded = new BitSet(len);
54 }
55
56 public Object getId() {
57 return _oid;
58 }
59
60 public Class getType() {
61 return _type;
62 }
63
64 public BitSet getLoaded() {
65 return _loaded;
66 }
67
68 public Object getData(int index) {
69 // make sure index is actually loaded to avoid returning an
70 // intermediate value
71 return (_loaded.get(index)) ? _data[index] : null;
72 }
73
74 public void setData(int index, Object val) {
75 _loaded.set(index);
76 _data[index] = val;
77 }
78
79 public void clearData(int index) {
80 _loaded.clear(index);
81 _data[index] = null;
82 }
83
84 public Object getImplData() {
85 return _impl;
86 }
87
88 public void setImplData(Object val) {
89 _impl = val;
90 }
91
92 public Object getImplData(int index) {
93 return (_fieldImpl != null) ? _fieldImpl[index] : null;
94 }
95
96 public void setImplData(int index, Object val) {
97 if (val != null) {
98 if (_fieldImpl == null)
99 _fieldImpl = new Object[_data.length];
100 _fieldImpl[index] = val;
101 } else if (_fieldImpl != null)
102 _fieldImpl[index] = null;
103 }
104
105 public Object getIntermediate(int index) {
106 return (!_loaded.get(index)) ? _data[index] : null;
107 }
108
109 public void setIntermediate(int index, Object val) {
110 _loaded.clear(index);
111 _data[index] = val;
112 }
113
114 public boolean isLoaded(int index) {
115 return _loaded.get(index);
116 }
117
118 public void setLoaded(int index, boolean loaded) {
119 if (loaded)
120 _loaded.set(index);
121 else
122 _loaded.clear(index);
123 }
124
125 public Object getVersion() {
126 return _version;
127 }
128
129 public void setVersion(Object version) {
130 _version = version;
131 }
132
133 public void load(OpenJPAStateManager sm, FetchConfiguration fetch,
134 Object context) {
135 loadVersion(sm);
136 loadImplData(sm);
137
138 FieldMetaData[] fmds = sm.getMetaData().getFields();
139 ((StateManagerImpl)sm).setLoading(true);
140 for (int i = 0; i < fmds.length; i++) {
141 // load intermediate data for all unloaded fields and data for
142 // fields in configured fetch groups
143 if (!isLoaded(i))
144 loadIntermediate(sm, fmds[i]);
145 else if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i])
146 != FetchConfiguration.FETCH_NONE)
147 loadField(sm, fmds[i], fetch, context);
148 }
149 }
150
151 public void load(OpenJPAStateManager sm, BitSet fields,
152 FetchConfiguration fetch, Object context) {
153 loadVersion(sm);
154 loadImplData(sm);
155
156 // attempt to load given fields
157 int len = (fields == null) ? 0 : fields.length();
158 FieldMetaData fmd;
159 for (int i = 0; i < len; i++) {
160 if (!fields.get(i))
161 continue;
162
163 fmd = sm.getMetaData().getField(i);
164 if (!isLoaded(i))
165 loadIntermediate(sm, fmd);
166 else {
167 loadField(sm, fmd, fetch, context);
168 loadImplData(sm, fmd);
169 fields.clear(i);
170 }
171 }
172 }
173
174 /**
175 * Set version information into the given state manager.
176 */
177 protected void loadVersion(OpenJPAStateManager sm) {
178 if (sm.getVersion() == null)
179 sm.setVersion(getVersion());
180 }
181
182 /**
183 * Set impl data information into the given state manager.
184 */
185 protected void loadImplData(OpenJPAStateManager sm) {
186 Object impl = getImplData();
187 if (sm.getImplData() == null && impl != null)
188 sm.setImplData(impl, true);
189 }
190
191 /**
192 * Set field-level information into the given state manager.
193 */
194 protected void loadField(OpenJPAStateManager sm, FieldMetaData fmd,
195 FetchConfiguration fetch, Object context) {
196 int index = fmd.getIndex();
197 Object val = toField(sm, fmd, getData(index), fetch, context);
198 sm.storeField(index, val);
199 }
200
201 /**
202 * Set field-level impl data into the given state manager.
203 */
204 protected void loadImplData(OpenJPAStateManager sm, FieldMetaData fmd) {
205 int index = fmd.getIndex();
206 Object impl = getImplData(index);
207 if (impl != null)
208 sm.setImplData(index, impl);
209 }
210
211 /**
212 * Set intermediate information for the given field into the state manager.
213 */
214 protected void loadIntermediate(OpenJPAStateManager sm, FieldMetaData fmd) {
215 int index = fmd.getIndex();
216 Object inter = getIntermediate(index);
217 if (inter != null && !sm.getLoaded().get(index))
218 sm.setIntermediate(index, inter);
219 }
220
221 public void store(OpenJPAStateManager sm) {
222 storeVersion(sm);
223 storeImplData(sm);
224
225 FieldMetaData[] fmds = sm.getMetaData().getFields();
226 for (int i = 0; i < fmds.length; i++) {
227 if (sm.getLoaded().get(i)) {
228 storeField(sm, fmds[i]);
229 storeImplData(sm, fmds[i], isLoaded(i));
230 } else if (!isLoaded(i))
231 storeIntermediate(sm, fmds[i]);
232 }
233 }
234
235 public void store(OpenJPAStateManager sm, BitSet fields) {
236 storeVersion(sm);
237 storeImplData(sm);
238
239 FieldMetaData[] fmds = sm.getMetaData().getFields();
240 for (int i = 0; i < fmds.length; i++) {
241 if (fields != null && fields.get(i)) {
242 storeField(sm, fmds[i]);
243 storeImplData(sm, fmds[i], isLoaded(i));
244 } else if (!isLoaded(i))
245 storeIntermediate(sm, fmds[i]);
246 }
247 }
248
249 /**
250 * Store version information from the given state manager.
251 */
252 protected void storeVersion(OpenJPAStateManager sm) {
253 setVersion(sm.getVersion());
254 }
255
256 /**
257 * Store impl data from the given state manager.
258 */
259 protected void storeImplData(OpenJPAStateManager sm) {
260 if (sm.isImplDataCacheable())
261 setImplData(sm.getImplData());
262 }
263
264 /**
265 * Store field-level information from the given state manager.
266 */
267 protected void storeField(OpenJPAStateManager sm, FieldMetaData fmd) {
268 if (fmd.getManagement() != fmd.MANAGE_PERSISTENT)
269 return;
270
271 int index = fmd.getIndex();
272 Object val = toData(fmd, sm.fetchField(index, false),
273 sm.getContext());
274 if (val != NULL)
275 setData(index, val);
276 else // unable to store field value; clear out any old values
277 clearData(index);
278 }
279
280 /**
281 * Store the intermediate field value for the given field.
282 */
283 protected void storeIntermediate(OpenJPAStateManager sm,
284 FieldMetaData fmd) {
285 int index = fmd.getIndex();
286 Object val = sm.getIntermediate(index);
287 if (val != null)
288 setIntermediate(index, val);
289 }
290
291 /**
292 * Store impl data for the given field.
293 */
294 protected void storeImplData(OpenJPAStateManager sm, FieldMetaData fmd,
295 boolean fieldLoaded) {
296 int index = fmd.getIndex();
297 if (fieldLoaded) {
298 // is there impl data to store?
299 Object impl = sm.getImplData(index);
300 if (impl != null && sm.isImplDataCacheable(index))
301 setImplData(index, impl);
302 } else
303 setImplData(index, null);
304 }
305
306 /**
307 * Return a new {@link PCData} implementation of the right type for
308 * embedded instances. Returns a {@link PCDataImpl} by default.
309 */
310 public AbstractPCData newEmbeddedPCData(OpenJPAStateManager sm) {
311 return new PCDataImpl(sm.getId (), sm.getMetaData ());
312 }
313 }