package org.jboss.ejb.plugins.cmp.jdbc.bridge;
import java.lang.reflect.Field;
import javax.ejb.EJBException;
import org.jboss.deployment.DeploymentException;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.plugins.cmp.jdbc.JDBCContext;
import org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
public class JDBCCMP1xFieldBridge extends JDBCAbstractCMPFieldBridge
{
private Field field;
public JDBCCMP1xFieldBridge(JDBCStoreManager manager,
JDBCCMPFieldMetaData metadata)
throws DeploymentException
{
super(manager, metadata);
try
{
field = manager.getMetaData().getEntityClass().getField(getFieldName());
}
catch(NoSuchFieldException e)
{
throw new DeploymentException("No field named '" + getFieldName() +
"' found in entity class.");
}
}
public Object getInstanceValue(EntityEnterpriseContext ctx)
{
FieldState fieldState = getFieldState(ctx);
if(!fieldState.isLoaded())
{
throw new EJBException("CMP 1.1 field not loaded: " + getFieldName());
}
try
{
return field.get(ctx.getInstance());
}
catch(Exception e)
{
throw new EJBException("Internal error getting instance field " +
getFieldName(), e);
}
}
public void setInstanceValue(EntityEnterpriseContext ctx, Object value)
{
try
{
field.set(ctx.getInstance(), value);
FieldState fieldState = getFieldState(ctx);
fieldState.setLoaded();
fieldState.setCheckDirty();
}
catch(Exception e)
{
throw new EJBException("Internal error setting instance field " +
getFieldName(), e);
}
}
public Object getLockedValue(EntityEnterpriseContext ctx)
{
throw new UnsupportedOperationException("Optimistic locking is not supported in CMP1.1.");
}
public void lockInstanceValue(EntityEnterpriseContext ctx)
{
}
public boolean isLoaded(EntityEnterpriseContext ctx)
{
return getFieldState(ctx).isLoaded();
}
public boolean isDirty(EntityEnterpriseContext ctx)
{
if(isReadOnly() || isPrimaryKeyMember())
{
return false;
}
return isLoaded(ctx) && !stateFactory.isStateValid(getInstanceValue(ctx), getFieldState(ctx).originalValue);
}
public void setClean(EntityEnterpriseContext ctx)
{
FieldState fieldState = getFieldState(ctx);
fieldState.originalValue = getInstanceValue(ctx);
if(isReadOnly())
{
fieldState.lastRead = System.currentTimeMillis();
}
}
public boolean isReadTimedOut(EntityEnterpriseContext ctx)
{
if(!isReadOnly())
{
return true;
}
if(getReadTimeOut() == -1)
{
return false;
}
long readInterval = System.currentTimeMillis() -
getFieldState(ctx).lastRead;
return readInterval >= getReadTimeOut();
}
public void resetPersistenceContext(EntityEnterpriseContext ctx)
{
if(isReadTimedOut(ctx))
{
JDBCContext jdbcCtx = (JDBCContext)ctx.getPersistenceContext();
FieldState fieldState = (FieldState)jdbcCtx.getFieldState(jdbcContextIndex);
if(fieldState != null)
fieldState.reset();
}
}
protected void setDirtyAfterGet(EntityEnterpriseContext ctx)
{
getFieldState(ctx).setCheckDirty();
}
private FieldState getFieldState(EntityEnterpriseContext ctx)
{
JDBCContext jdbcCtx = (JDBCContext)ctx.getPersistenceContext();
FieldState fieldState = (FieldState)jdbcCtx.getFieldState(jdbcContextIndex);
if(fieldState == null)
{
fieldState = new FieldState(jdbcCtx);
jdbcCtx.setFieldState(jdbcContextIndex, fieldState);
}
return fieldState;
}
private class FieldState
{
private Object originalValue;
private long lastRead = -1;
private JDBCEntityBridge.EntityState entityState;
public FieldState(JDBCContext jdbcContext)
{
this.entityState = jdbcContext.getEntityState();
}
public boolean isLoaded()
{
return entityState.isLoaded(tableIndex);
}
public void setLoaded()
{
entityState.setLoaded(tableIndex);
}
public void setCheckDirty()
{
entityState.setCheckDirty(tableIndex);
}
public void reset()
{
originalValue = null;
lastRead = -1;
entityState.resetFlags(tableIndex);
log.debug("reset field state");
}
}
}