package org.jboss.ejb.plugins.cmp.jdbc2.bridge;
import org.jboss.deployment.DeploymentException;
import org.jboss.ejb.EntityContainer;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.plugins.cmp.bridge.EntityBridgeInvocationHandler;
import org.jboss.ejb.plugins.cmp.bridge.FieldBridge;
import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore;
import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractEntityBridge;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractCMRFieldBridge;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationshipRoleMetaData;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCOptimisticLockingMetaData;
import org.jboss.ejb.plugins.cmp.jdbc2.JDBCStoreManager2;
import org.jboss.ejb.plugins.cmp.jdbc2.PersistentContext;
import org.jboss.ejb.plugins.cmp.jdbc2.schema.EntityTable;
import org.jboss.logging.Logger;
import org.jboss.proxy.compiler.InvocationHandler;
import org.jboss.proxy.compiler.Proxies;
import javax.ejb.EJBException;
import javax.ejb.RemoveException;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JDBCEntityBridge2
implements JDBCAbstractEntityBridge
{
private final JDBCStoreManager2 manager;
private final JDBCEntityMetaData metadata;
private final EntityTable table;
private final String tableName;
private final Logger log;
private JDBCCMPFieldBridge2[] pkFields;
private JDBCCMPFieldBridge2[] cmpFields;
private JDBCCMPFieldBridge2[] tableFields;
private JDBCCMRFieldBridge2[] cmrFields;
private JDBCCMPFieldBridge2 versionField;
private int cmrCount;
public JDBCEntityBridge2(JDBCStoreManager2 manager, JDBCEntityMetaData metadata) throws DeploymentException
{
this.manager = manager;
this.metadata = metadata;
log = Logger.getLogger(this.getClass().getName() + "." + metadata.getName());
table = manager.getSchema().createEntityTable(metadata, this);
tableName = SQLUtil.getTableNameWithoutSchema(metadata.getDefaultTableName());
}
public void init() throws DeploymentException
{
loadCMPFields(metadata);
loadCMRFields(metadata);
JDBCOptimisticLockingMetaData olMD = metadata.getOptimisticLocking();
if(olMD != null)
{
if(olMD.getLockingStrategy() != JDBCOptimisticLockingMetaData.VERSION_COLUMN_STRATEGY)
{
throw new DeploymentException(
"Only version-column optimistic locking strategy is supported at the moment.");
}
JDBCCMPFieldMetaData versionMD = olMD.getLockingField();
versionField = (JDBCCMPFieldBridge2) getFieldByName(versionMD.getFieldName());
}
}
public JDBCCMPFieldBridge2 getVersionField()
{
return versionField;
}
public void resolveRelationships() throws DeploymentException
{
for(int i = 0; i < cmrFields.length; ++i)
{
cmrFields[i].resolveRelationship();
}
}
public void start() throws DeploymentException
{
if(versionField != null)
{
versionField.initVersion();
}
table.start();
if(cmrFields != null)
{
for(int i = 0; i < cmrFields.length; ++i)
{
cmrFields[i].initLoader();
}
}
}
public void stop() throws Exception
{
table.stop();
}
public JDBCEntityMetaData getMetaData()
{
return metadata;
}
public EntityTable getTable()
{
return table;
}
public JDBCFieldBridge[] getPrimaryKeyFields()
{
return pkFields;
}
public JDBCFieldBridge[] getTableFields()
{
return tableFields;
}
public JDBCAbstractCMRFieldBridge[] getCMRFields()
{
return cmrFields;
}
public JDBCEntityPersistenceStore getManager()
{
return manager;
}
public EntityContainer getContainer()
{
return manager.getContainer();
}
public Object extractPrimaryKeyFromInstance(EntityEnterpriseContext ctx)
{
try
{
Object pk = null;
for(int i = 0; i < pkFields.length; ++i)
{
JDBCCMPFieldBridge2 pkField = pkFields[i];
Object fieldValue = pkField.getValue(ctx);
pk = pkField.setPrimaryKeyValue(pk, fieldValue);
}
return pk;
}
catch(EJBException e)
{
throw e;
}
catch(Exception e)
{
throw new EJBException("Internal error extracting primary key from instance", e);
}
}
public static void destroyPersistenceContext(EntityEnterpriseContext ctx)
{
Object instance = ctx.getInstance();
if(instance instanceof Proxies.ProxyTarget)
{
InvocationHandler handler = ((Proxies.ProxyTarget) instance).getInvocationHandler();
if(handler instanceof EntityBridgeInvocationHandler)
{
((EntityBridgeInvocationHandler) handler).setContext(null);
}
}
ctx.setPersistenceContext(null);
}
public void initPersistenceContext(EntityEnterpriseContext ctx)
{
Object instance = ctx.getInstance();
if(instance instanceof Proxies.ProxyTarget)
{
InvocationHandler handler = ((Proxies.ProxyTarget) instance).getInvocationHandler();
if(handler instanceof EntityBridgeInvocationHandler)
{
((EntityBridgeInvocationHandler) handler).setContext(ctx);
}
}
}
public void initInstance(EntityEnterpriseContext ctx)
{
ctx.setPersistenceContext(new PersistentContext(this, table.getRow(ctx.getId())));
for(int i = 0; i < tableFields.length; ++i)
{
tableFields[i].initInstance(ctx);
}
for(int i = 0; i < cmrFields.length; ++i)
{
cmrFields[i].initInstance(ctx);
}
}
public List getFields()
{
List fields = new ArrayList();
for(int i = 0; i < pkFields.length; ++i)
{
fields.add(pkFields[i]);
}
for(int i = 0; i < cmpFields.length; ++i)
{
fields.add(cmpFields[i]);
}
for(int i = 0; i < cmrFields.length; ++i)
{
fields.add(cmrFields[i]);
}
return fields;
}
public boolean isStoreRequired(EntityEnterpriseContext instance)
{
PersistentContext pctx = (PersistentContext) instance.getPersistenceContext();
return pctx.isDirty();
}
public boolean isModified(EntityEnterpriseContext instance)
{
PersistentContext pctx = (PersistentContext) instance.getPersistenceContext();
boolean modified = pctx.isDirty();
if(!modified && cmrFields != null)
{
for(int i = 0; i < cmrFields.length; ++i)
{
final JDBCCMRFieldBridge2.FieldState cmrState = pctx.getCMRState(i);
if(cmrState != null && cmrState.isModified())
{
modified = true;
break;
}
}
}
return modified;
}
public Class getPrimaryKeyClass()
{
return metadata.getPrimaryKeyClass();
}
public Class getHomeClass()
{
return metadata.getHomeClass();
}
public Class getLocalHomeClass()
{
return metadata.getLocalHomeClass();
}
public String getTableName()
{
return tableName;
}
public String getQualifiedTableName()
{
return metadata.getDefaultTableName();
}
public DataSource getDataSource()
{
return table.getDataSource();
}
public boolean[] getLoadGroupMask(String eagerLoadGroupName)
{
throw new UnsupportedOperationException();
}
public int getNextCMRIndex()
{
return cmrCount++;
}
public void remove(EntityEnterpriseContext ctx) throws RemoveException
{
if(cmrFields != null)
{
for(int i = 0; i < cmrFields.length; ++i)
{
cmrFields[i].remove(ctx);
}
}
}
public String getEntityName()
{
return metadata.getName();
}
public String getAbstractSchemaName()
{
return metadata.getAbstractSchemaName();
}
public FieldBridge getFieldByName(String fieldName)
{
FieldBridge field;
for(int i = 0; i < pkFields.length; ++i)
{
field = pkFields[i];
if(field.getFieldName().equals(fieldName))
{
return field;
}
}
for(int i = 0; i < cmpFields.length; ++i)
{
field = cmpFields[i];
if(field.getFieldName().equals(fieldName))
{
return field;
}
}
for(int i = 0; i < cmrFields.length; ++i)
{
field = cmrFields[i];
if(field.getFieldName().equals(fieldName))
{
return field;
}
}
throw new IllegalStateException("Field " + fieldName + " not found in entity " + getEntityName());
}
public Class getRemoteInterface()
{
return metadata.getRemoteClass();
}
public Class getLocalInterface()
{
return metadata.getLocalClass();
}
JDBCCMPFieldBridge2 addTableField(JDBCCMPFieldMetaData metadata) throws DeploymentException
{
table.addField();
if(tableFields == null)
{
tableFields = new JDBCCMPFieldBridge2[1];
}
else
{
JDBCCMPFieldBridge2[] tmp = tableFields;
tableFields = new JDBCCMPFieldBridge2[tableFields.length + 1];
System.arraycopy(tmp, 0, tableFields, 0, tmp.length);
}
int tableIndex = tableFields.length - 1;
JDBCCMPFieldBridge2 cmpField = new JDBCCMPFieldBridge2(manager, this, metadata, tableIndex);
tableFields[tableFields.length - 1] = cmpField;
return cmpField;
}
private void loadCMPFields(JDBCEntityMetaData metadata) throws DeploymentException
{
List cmpFieldsList = new ArrayList(metadata.getCMPFields().size());
List pkFieldsList = new ArrayList(metadata.getCMPFields().size());
Iterator iter = metadata.getCMPFields().iterator();
while(iter.hasNext())
{
JDBCCMPFieldMetaData cmpFieldMetaData = (JDBCCMPFieldMetaData) iter.next();
JDBCCMPFieldBridge2 cmpField = addTableField(cmpFieldMetaData);
if(cmpFieldMetaData.isPrimaryKeyMember())
{
pkFieldsList.add(cmpField);
}
else
{
cmpFieldsList.add(cmpField);
}
}
pkFields = new JDBCCMPFieldBridge2[pkFieldsList.size()];
for(int i = 0; i < pkFieldsList.size(); ++i)
{
pkFields[i] = (JDBCCMPFieldBridge2) pkFieldsList.get(i);
}
cmpFields = new JDBCCMPFieldBridge2[metadata.getCMPFields().size() - pkFields.length];
int cmpFieldIndex = 0;
for(int i = 0; i < cmpFieldsList.size(); ++i)
{
cmpFields[cmpFieldIndex++] = (JDBCCMPFieldBridge2) cmpFieldsList.get(i);
}
}
private void loadCMRFields(JDBCEntityMetaData metadata)
throws DeploymentException
{
cmrFields = new JDBCCMRFieldBridge2[metadata.getRelationshipRoles().size()];
int cmrFieldIndex = 0;
for(Iterator iter = metadata.getRelationshipRoles().iterator(); iter.hasNext();)
{
JDBCRelationshipRoleMetaData relationshipRole = (JDBCRelationshipRoleMetaData) iter.next();
JDBCCMRFieldBridge2 cmrField = new JDBCCMRFieldBridge2(this, manager, relationshipRole);
cmrFields[cmrFieldIndex++] = cmrField;
}
}
}