package jef.database.dialect.type;
import java.sql.SQLException;
import java.util.List;
import jef.accelerator.bean.BeanAccessor;
import jef.database.Field;
import jef.database.IQueryableEntity;
import jef.database.annotation.DateGenerateType;
import jef.database.dialect.ColumnType;
import jef.database.dialect.DatabaseDialect;
import jef.database.meta.ITableMetadata;
import jef.database.query.BindVariableField;
import jef.database.wrapper.clause.InsertSqlClause;
import jef.database.wrapper.clause.UpdateClause;
import jef.database.wrapper.processor.InsertStepAdapter;
import jef.database.wrapper.variable.ConstantVariable;
import jef.tools.Assert;
import jef.tools.reflect.Property;
public abstract class AbstractVersionNumberMapping extends AColumnMapping implements VersionSupportColumn {
private boolean version;
private Property accessor;
protected DateGenerateType dateType;
private Processor STEP;
private static abstract class Processor extends InsertStepAdapter {
abstract void update(String columnName, UpdateClause update);
abstract Object getNextValue(Object current);
}
private static class InsertTime extends Processor {
private Property accessor;
private AbstractVersionNumberMapping parent;
private DateGenerateType dateType;
InsertTime(AbstractVersionNumberMapping parent) {
this.parent = parent;
this.accessor = parent.accessor;
this.dateType=parent.dateType;
Assert.notNull(dateType);
Assert.notNull(accessor);
}
public void callBefore(List<? extends IQueryableEntity> data) throws SQLException {
for (IQueryableEntity q : data) {
accessor.set(q, parent.transfer(dateType.generateLong()));
}
}
void update(String columnName, UpdateClause result) {
result.addEntry(columnName, new ConstantVariable(parent.transfer(dateType.generateLong())));
}
Object getNextValue(Object current) {
return parent.transfer(dateType.generateLong());
}
};
private static class InsertNum extends Processor {
private Property accessor;
private AbstractVersionNumberMapping parent;
InsertNum(AbstractVersionNumberMapping parent) {
this.parent = parent;
this.accessor = parent.accessor;
Assert.notNull(accessor);
}
public void callBefore(List<? extends IQueryableEntity> data) throws SQLException {
for (IQueryableEntity q : data) {
accessor.set(q, parent.transfer(1L));
}
}
void update(String columnName, UpdateClause result) {
result.addEntry(columnName, columnName + "+1");
}
Object getNextValue(Object current) {
return parent.increament(current);
}
};
@Override
public void init(Field field, String columnName, ColumnType type, ITableMetadata meta) {
super.init(field, columnName, type, meta);
BeanAccessor ba = meta.getContainerAccessor();
accessor = ba.getProperty(field.name());
if (type instanceof ColumnType.Int) {
this.version = ((ColumnType.Int) type).isVersion();
this.dateType = ((ColumnType.Int) type).getGenerateType();
if (dateType != null) {
STEP = new InsertTime(this);
} else {
STEP = new InsertNum(this);
}
}
}
@Override
public void processPreparedInsert(IQueryableEntity obj, List<String> cStr, List<String> vStr, InsertSqlClause result, boolean dynamic) throws SQLException {
if (!obj.isUsed(field) && version) {
result.getCallback().addProcessor(STEP);
}
super.processPreparedInsert(obj, cStr, vStr, result, dynamic);
}
@Override
public void processAutoUpdate(DatabaseDialect profile, UpdateClause result) {
String columnName = getColumnName(profile, true);
STEP.update(columnName, result);
}
@Override
public boolean isVersion() {
return version;
}
@Override
public Object getAutoUpdateValue(DatabaseDialect profile, Object bean) {
Object value = accessor.get(bean);
value = STEP.getNextValue(value);
accessor.set(bean, value);
return value;
}
abstract Object increament(Object value);
protected abstract Object transfer(long n);
@Override
public boolean isUpdateAlways() {
return version;
}
@Override
public boolean isGenerated() {
return version;
}
}