blob: 7b3233a7e5335b6227aecd3ad8aabca795a3647c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.kernel;
import java.util.BitSet;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
/**
* Default {@link PCData} implementation.
*
* @author Patrick Linskey
* @author Abe White
* @nojavadoc
*/
public class PCDataImpl
extends AbstractPCData {
private final Object _oid;
private final Class _type;
private final Object[] _data;
private final BitSet _loaded;
private Object _version = null;
private Object _impl = null;
private Object[] _fieldImpl = null;
/**
* Constructor.
*/
public PCDataImpl(Object oid, ClassMetaData meta) {
_oid = oid;
_type = meta.getDescribedType();
int len = meta.getFields().length;
_data = new Object[len];
_loaded = new BitSet(len);
}
public Object getId() {
return _oid;
}
public Class getType() {
return _type;
}
public BitSet getLoaded() {
return _loaded;
}
public Object getData(int index) {
// make sure index is actually loaded to avoid returning an
// intermediate value
return (_loaded.get(index)) ? _data[index] : null;
}
public void setData(int index, Object val) {
_loaded.set(index);
_data[index] = val;
}
public void clearData(int index) {
_loaded.clear(index);
_data[index] = null;
}
public Object getImplData() {
return _impl;
}
public void setImplData(Object val) {
_impl = val;
}
public Object getImplData(int index) {
return (_fieldImpl != null) ? _fieldImpl[index] : null;
}
public void setImplData(int index, Object val) {
if (val != null) {
if (_fieldImpl == null)
_fieldImpl = new Object[_data.length];
_fieldImpl[index] = val;
} else if (_fieldImpl != null)
_fieldImpl[index] = null;
}
public Object getIntermediate(int index) {
return (!_loaded.get(index)) ? _data[index] : null;
}
public void setIntermediate(int index, Object val) {
_loaded.clear(index);
_data[index] = val;
}
public boolean isLoaded(int index) {
return _loaded.get(index);
}
public void setLoaded(int index, boolean loaded) {
if (loaded)
_loaded.set(index);
else
_loaded.clear(index);
}
public Object getVersion() {
return _version;
}
public void setVersion(Object version) {
_version = version;
}
public void load(OpenJPAStateManager sm, FetchConfiguration fetch,
Object context) {
loadVersion(sm);
loadImplData(sm);
FieldMetaData[] fmds = sm.getMetaData().getFields();
((StateManagerImpl)sm).setLoading(true);
for (int i = 0; i < fmds.length; i++) {
// load intermediate data for all unloaded fields and data for
// fields in configured fetch groups
if (!isLoaded(i))
loadIntermediate(sm, fmds[i]);
else if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i])
!= FetchConfiguration.FETCH_NONE)
loadField(sm, fmds[i], fetch, context);
}
}
public void load(OpenJPAStateManager sm, BitSet fields,
FetchConfiguration fetch, Object context) {
loadVersion(sm);
loadImplData(sm);
// attempt to load given fields
int len = (fields == null) ? 0 : fields.length();
FieldMetaData fmd;
for (int i = 0; i < len; i++) {
if (!fields.get(i))
continue;
fmd = sm.getMetaData().getField(i);
if (!isLoaded(i))
loadIntermediate(sm, fmd);
else {
loadField(sm, fmd, fetch, context);
loadImplData(sm, fmd);
fields.clear(i);
}
}
}
/**
* Set version information into the given state manager.
*/
protected void loadVersion(OpenJPAStateManager sm) {
if (sm.getVersion() == null)
sm.setVersion(getVersion());
}
/**
* Set impl data information into the given state manager.
*/
protected void loadImplData(OpenJPAStateManager sm) {
Object impl = getImplData();
if (sm.getImplData() == null && impl != null)
sm.setImplData(impl, true);
}
/**
* Set field-level information into the given state manager.
*/
protected void loadField(OpenJPAStateManager sm, FieldMetaData fmd,
FetchConfiguration fetch, Object context) {
int index = fmd.getIndex();
Object val = toField(sm, fmd, getData(index), fetch, context);
sm.storeField(index, val);
}
/**
* Set field-level impl data into the given state manager.
*/
protected void loadImplData(OpenJPAStateManager sm, FieldMetaData fmd) {
int index = fmd.getIndex();
Object impl = getImplData(index);
if (impl != null)
sm.setImplData(index, impl);
}
/**
* Set intermediate information for the given field into the state manager.
*/
protected void loadIntermediate(OpenJPAStateManager sm, FieldMetaData fmd) {
int index = fmd.getIndex();
Object inter = getIntermediate(index);
if (inter != null && !sm.getLoaded().get(index))
sm.setIntermediate(index, inter);
}
public void store(OpenJPAStateManager sm) {
storeVersion(sm);
storeImplData(sm);
FieldMetaData[] fmds = sm.getMetaData().getFields();
for (int i = 0; i < fmds.length; i++) {
if (sm.getLoaded().get(i)) {
storeField(sm, fmds[i]);
storeImplData(sm, fmds[i], isLoaded(i));
} else if (!isLoaded(i))
storeIntermediate(sm, fmds[i]);
}
}
public void store(OpenJPAStateManager sm, BitSet fields) {
storeVersion(sm);
storeImplData(sm);
FieldMetaData[] fmds = sm.getMetaData().getFields();
for (int i = 0; i < fmds.length; i++) {
if (fields != null && fields.get(i)) {
storeField(sm, fmds[i]);
storeImplData(sm, fmds[i], isLoaded(i));
} else if (!isLoaded(i))
storeIntermediate(sm, fmds[i]);
}
}
/**
* Store version information from the given state manager.
*/
protected void storeVersion(OpenJPAStateManager sm) {
setVersion(sm.getVersion());
}
/**
* Store impl data from the given state manager.
*/
protected void storeImplData(OpenJPAStateManager sm) {
if (sm.isImplDataCacheable())
setImplData(sm.getImplData());
}
/**
* Store field-level information from the given state manager.
*/
protected void storeField(OpenJPAStateManager sm, FieldMetaData fmd) {
if (fmd.getManagement() != fmd.MANAGE_PERSISTENT)
return;
int index = fmd.getIndex();
Object val = toData(fmd, sm.fetchField(index, false),
sm.getContext());
if (val != NULL)
setData(index, val);
else // unable to store field value; clear out any old values
clearData(index);
}
/**
* Store the intermediate field value for the given field.
*/
protected void storeIntermediate(OpenJPAStateManager sm,
FieldMetaData fmd) {
int index = fmd.getIndex();
Object val = sm.getIntermediate(index);
if (val != null)
setIntermediate(index, val);
}
/**
* Store impl data for the given field.
*/
protected void storeImplData(OpenJPAStateManager sm, FieldMetaData fmd,
boolean fieldLoaded) {
int index = fmd.getIndex();
if (fieldLoaded) {
// is there impl data to store?
Object impl = sm.getImplData(index);
if (impl != null && sm.isImplDataCacheable(index))
setImplData(index, impl);
} else
setImplData(index, null);
}
/**
* Return a new {@link PCData} implementation of the right type for
* embedded instances. Returns a {@link PCDataImpl} by default.
*/
public AbstractPCData newEmbeddedPCData(OpenJPAStateManager sm) {
return new PCDataImpl(sm.getId (), sm.getMetaData ());
}
}