All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.venky.swf.db.table.ModelInvocationHandler Maven / Gradle / Ivy

The newest version!
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.venky.swf.db.table;


import com.venky.cache.Cache;
import com.venky.core.collections.IgnoreCaseList;
import com.venky.core.collections.LowerCaseStringCache;
import com.venky.core.collections.SequenceMap;
import com.venky.core.collections.SequenceSet;
import com.venky.core.log.SWFLogger;
import com.venky.core.log.TimerStatistics.Timer;
import com.venky.core.string.StringUtil;
import com.venky.core.util.MultiException;
import com.venky.core.util.ObjectUtil;
import com.venky.extension.Registry;
import com.venky.swf.db.Database;
import com.venky.swf.db.JdbcTypeHelper.TypeConverter;
import com.venky.swf.db.JdbcTypeHelper.TypeRef;
import com.venky.swf.db.annotations.column.COLUMN_DEF;
import com.venky.swf.db.annotations.column.IS_VIRTUAL;
import com.venky.swf.db.annotations.column.defaulting.StandardDefaulter;
import com.venky.swf.db.annotations.column.pm.PARTICIPANT;
import com.venky.swf.db.annotations.column.relationship.CONNECTED_VIA;
import com.venky.swf.db.annotations.column.validations.processors.DateFormatValidator;
import com.venky.swf.db.annotations.column.validations.processors.EnumerationValidator;
import com.venky.swf.db.annotations.column.validations.processors.ExactLengthValidator;
import com.venky.swf.db.annotations.column.validations.processors.FieldValidator;
import com.venky.swf.db.annotations.column.validations.processors.IntegerRangeValidator;
import com.venky.swf.db.annotations.column.validations.processors.MaxLengthValidator;
import com.venky.swf.db.annotations.column.validations.processors.MinLengthValidator;
import com.venky.swf.db.annotations.column.validations.processors.NotNullValidator;
import com.venky.swf.db.annotations.column.validations.processors.NumericRangeValidator;
import com.venky.swf.db.annotations.column.validations.processors.RegExValidator;
import com.venky.swf.db.annotations.model.CONFIGURATION;
import com.venky.swf.db.annotations.model.validations.ModelValidator;
import com.venky.swf.db.annotations.model.validations.UniqueKeyValidator;
import com.venky.swf.db.model.Model;
import com.venky.swf.db.model.User;
import com.venky.swf.db.model.reflection.ModelReflector;
import com.venky.swf.db.table.Table.ColumnDescriptor;
import com.venky.swf.exceptions.AccessDeniedException;
import com.venky.swf.routing.Config;
import com.venky.swf.sql.Conjunction;
import com.venky.swf.sql.Delete;
import com.venky.swf.sql.Expression;
import com.venky.swf.sql.Insert;
import com.venky.swf.sql.Operator;
import com.venky.swf.sql.Select;
import com.venky.swf.sql.Update;
import com.venky.swf.sql.parser.SQLExpressionParser;
import com.venky.swf.util.SharedKeys;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

/**
 *
 * @author venky
 */
public class ModelInvocationHandler implements InvocationHandler {

    private Record record = null;
    private Class modelClass = null;
    private List virtualFields = new IgnoreCaseList(false);
    private String modelName = null;

    private transient Model proxy = null;
    private transient ModelReflector reflector = null;

	@SuppressWarnings("unchecked")
	public  ModelReflector getReflector() {
		if (reflector == null) { 
			reflector = ModelReflector.instance(modelClass);
		}
		return (ModelReflector) reflector;
	}
	
	public String getModelName(){
		return modelName;
	}
	
	public String getPool(){
		return getReflector().getPool();
	}
	
	public Class getModelClass(){ 
		return modelClass;
	}
	
	
	/**
	 * Used for serialization.:
	 */
	protected ModelInvocationHandler() {
		
	}
	public ModelInvocationHandler(Class modelClass, Record record) {
        this.record = record;
        this.modelClass = modelClass;
        
        this.reflector = ModelReflector.instance(modelClass);
        this.modelName = Table.getSimpleModelClassName(reflector.getTableName());
        this.virtualFields = reflector.getVirtualFields();
        record.startTracking(false);
    }
	public ModelInvocationHandler(Class modelClass, Model proxy){
		this.proxy = proxy;
		this.modelClass = modelClass;

		this.reflector = ModelReflector.instance(modelClass);
		this.modelName = Table.getSimpleModelClassName(reflector.getTableName());
		this.virtualFields = reflector.getVirtualFields();
		this.record = null;
	}
	
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	bootStrapProxy(getModelClass().cast(proxy));
        String mName = method.getName();
        Class retType = method.getReturnType();
        Class[] parameters = method.getParameterTypes();
        Record record = getRawRecord();

        if (getReflector().getFieldGetterSignatures().contains(getReflector().getSignature(method))) {
            String fieldName = getReflector().getFieldName(method);
            if (!virtualFields.contains(fieldName)){
                ColumnDescriptor cd = getReflector().getColumnDescriptor(fieldName);
                String columnName = cd.getName();

                Object value = record.get(columnName);

				TypeRef ref =Database.getJdbcTypeHelper(getPool()).getTypeRef(retType);
                TypeConverter converter = ref.getTypeConverter();
                if (value == null) {
                    COLUMN_DEF colDef = getReflector().getAnnotation(method, COLUMN_DEF.class);
                    if (colDef != null) {
                        value = StandardDefaulter.getDefaultValue(colDef.value(), colDef.args());
                    }
                }
                if (value == null){
                	if (retType.isPrimitive()){
                        return converter.valueOf(value);
                	}else {
                        return value;
                    }
                } else if (retType.isInstance(value) && !ref.isLOB()) {
                    return value;
                } else {
                    return converter.valueOf(value);
                }
            }
        } else if (getReflector().getFieldSetterSignatures().contains(getReflector().getSignature(method))) {
            String fieldName = StringUtil.underscorize(mName.substring(3));
            if (!virtualFields.contains(fieldName)){
                String columnName = getReflector().getColumnDescriptor(fieldName).getName(); 
                return record.put(columnName, args[0]);
            }
        } else if (getReflector().getReferredModelGetters().contains(method)) {
        	if (!getReflector().isAnnotationPresent(method,IS_VIRTUAL.class)){
                return getParent(method);
        	}
        } else if (getReflector().getChildGetters().contains(method)) {
        	if (!getReflector().isAnnotationPresent(method,IS_VIRTUAL.class)){
	        	CONNECTED_VIA join = getReflector().getAnnotation(method,CONNECTED_VIA.class);
	        	if (join != null){
	        		return getChildren(getReflector().getChildModelClass(method),join.value(),join.additional_join());
	        	}else {
	        		return getChildren(getReflector().getChildModelClass(method));
	        	}
        	}
        }
        
        /* Optimization 
        for (Object impl: modelImplObjects){
        	try {
	        	Method inModelImplClass = impl.getClass().getMethod(mName, parameters); 
	        	if (retType.isAssignableFrom(inModelImplClass.getReturnType())){
					Timer timer = startTimer(inModelImplClass.toString());
	        		try {
	        			return inModelImplClass.invoke(impl, args);
	        		}catch(InvocationTargetException ex){
	            		throw ex.getCause();
	            	}finally{
	        			timer.stop(); 
	        		}
	        	}
        	}catch(NoSuchMethodException ex){
        		//	
        	}
        }
        
        Method inCurrentClass = this.getClass().getMethod(mName, parameters);
        if (retType.isAssignableFrom(inCurrentClass.getReturnType())) {
        	try {
        		return inCurrentClass.invoke(this, args);
        	}catch (InvocationTargetException ex){
        		throw ex.getCause();
        	}
        } else {
            throw new NoSuchMethodException("Donot know how to execute this method");
        }
        
        */
        Class implClass = getMethodImplClass(method);
        Object implObject = null;
        if (implClass != null){
        	implObject = modelImplObjects.get(implClass);
        }
        if (implClass == null || implObject == null){ 
        	//implObject is null while constructing impls.
        	implClass = this.getClass();
        	implObject = this;
        }
    	Method inImplClass = implClass.getMethod(mName, parameters);
    	if (retType.isAssignableFrom(inImplClass.getReturnType())) {
	        Timer timer = cat().startTimer(inImplClass.toString());
	        try {
                if (implObject instanceof  ModelInvocationHandler) {
                    ((ModelInvocationHandler) implObject).bootStrapProxy(getModelClass().cast(proxy));
                }
	        	return inImplClass.invoke(implObject, args);
	        }catch (InvocationTargetException ex){
	        	throw ex.getCause();
	        }finally{
	        	timer.stop();
	        }
    	}else {
    		throw new NoSuchMethodException("Donot know how to execute " + getReflector().getSignature(method));
    	}
    }
    private SWFLogger cat() {
		return Config.instance().getLogger(getClass().getName()+"."+getModelName());
	}

    @SuppressWarnings("unchecked")
	public 

P getParent(Method parentGetter) { Class

parentClass = (Class

) parentGetter.getReturnType(); String parentIdFieldName = StringUtil.underscorize(parentGetter.getName().substring(3) +"Id"); Method parentIdGetter = this.getReflector().getFieldGetter(parentIdFieldName); Number parentId; try { parentId = (Number)parentIdGetter.invoke(proxy); } catch (Exception e) { throw new RuntimeException(parentIdFieldName,e); } P parent = null; if (parentId != null) { parent = Database.getTable(parentClass).get(parentId.longValue()); } return parent; } public List getChildren(Class childClass){ Class modelClass = getReflector().getModelClass(); ModelReflector childReflector = ModelReflector.instance(childClass); Expression expression = new Expression(childReflector.getPool(),Conjunction.OR); for (String fieldName: childReflector.getFields()){ if (fieldName.endsWith("_ID")){ Method fieldGetter = childReflector.getFieldGetter(fieldName); Method referredModelGetter = childReflector.getReferredModelGetterFor(fieldGetter); if (referredModelGetter != null && ObjectUtil.equals(referredModelGetter.getReturnType().getSimpleName(),modelClass.getSimpleName())){ String columnName = childReflector.getColumnDescriptor(fieldName).getName(); expression.add(new Expression(childReflector.getPool(),columnName,Operator.EQ,proxy.getId())); } } } if (expression.isEmpty()){ throw new RuntimeException("Don;t know how to getChildren of kind " + childClass.getSimpleName() + " for " + modelClass.getSimpleName()); } return getChildren(childClass,expression); } public List getChildren(Class childClass, String parentIdFieldName){ return getChildren(childClass,parentIdFieldName,null); } public List getChildren(Class childClass, String parentIdFieldName, String addnl_condition){ long parentId = proxy.getId(); ModelReflector childReflector = ModelReflector.instance(childClass); String parentIdColumnName = childReflector.getColumnDescriptor(parentIdFieldName).getName(); Expression where = new Expression(getPool(),Conjunction.AND); where.add(new Expression(getPool(),parentIdColumnName,Operator.EQ,new BindVariable(getPool(),parentId))); if (!ObjectUtil.isVoid(addnl_condition)){ Expression addnl = new SQLExpressionParser(childClass).parse(addnl_condition); where.add(addnl); } return getChildren(childClass, where); } public List getChildren(Class childClass, Expression expression){ Select q = new Select(); q.from(childClass); q.where(expression); q.orderBy(ModelReflector.instance(childClass).getOrderBy()); return q.execute(childClass); } public void setProxy(M proxy) { this.proxy = proxy; } @SuppressWarnings("unchecked") public M getProxy() { return (M)proxy; } public boolean isAccessibleBy(User user){ return isAccessibleBy(user, getReflector().getModelClass()); } public Set getParticipatingRoles(User user){ return getParticipatingRoles(user,getReflector().getModelClass()); } public Set getParticipatingRoles(User user,Class asModel){ if (!getReflector().reflects(asModel)){ throw new AccessDeniedException(); } return getParticipatingRoles(user.getParticipationOptions(asModel,getProxy())); } private Set getParticipatingRoles(Cache>> pGroupOptions){ Timer timer = cat().startTimer(); try { ModelReflector reflector = getReflector(); Set participatingRoles = new HashSet(); for (String participantRoleGroup : pGroupOptions.keySet()){ Map> pOptions = pGroupOptions.get(participantRoleGroup); Set participatingRolesInCurrentGroup = new HashSet(); for (String referencedModelIdFieldName :pOptions.keySet()){ Number referenceValue = reflector.get(getRawRecord(),referencedModelIdFieldName); PARTICIPANT participant = reflector.getAnnotation(reflector.getFieldGetter(referencedModelIdFieldName), PARTICIPANT.class); if (participant.redundant() || pOptions.get(referencedModelIdFieldName) == null || pOptions.get(referencedModelIdFieldName).contains(referenceValue)){ participatingRolesInCurrentGroup.add(reflector.getParticipatingRole(referencedModelIdFieldName)); } } if (!pOptions.isEmpty() && participatingRolesInCurrentGroup.isEmpty()){ throw new AccessDeniedException(); // User is not a participant on the model. } participatingRoles.addAll(participatingRolesInCurrentGroup); } return participatingRoles; }finally{ timer.stop(); } } public boolean isAccessibleBy(User user,Class asModel){ Timer timer = cat().startTimer(null,Config.instance().isTimerAdditive()); try { if (!getReflector().reflects(asModel)){ return false; } Set pRoles = getParticipatingRoles(user,asModel); return (pRoles != null);// It is always true. returning false depends on AccessDeniedException being thrown. }catch(AccessDeniedException ex){ return false; }finally{ timer.stop(); } } public Record getRawRecord(){ if (record != null){ return record; }else if (proxy != null){ ModelInvocationHandler invocationHandler = (ModelInvocationHandler) Proxy.getInvocationHandler(proxy); if (invocationHandler != this){ return invocationHandler.getRawRecord(); }else{ return null; } }else { return null; } } public void setRawRecord(Record record){ if (this.record != null){ this.record = record; }else if (proxy != null){ ModelInvocationHandler invocationHandler = (ModelInvocationHandler) Proxy.getInvocationHandler(proxy); if (invocationHandler != this){ invocationHandler.setRawRecord(record); }else{ this.record = record; } }else { this.record = record; } } public static void dispose(){ modelImplClassesCache.clear(); methodImplClassCache.clear(); } public static M getProxy(Class modelClass, Record record) { ModelReflector ref = ModelReflector.instance(modelClass); try { ModelInvocationHandler mImpl = new ModelInvocationHandler(modelClass, record); M m = modelClass.cast(Proxy.newProxyInstance(modelClass.getClassLoader(), ref.getClassHierarchies().toArray(new Class[]{}), mImpl)); mImpl.bootStrapProxy(m); return m; } catch (Exception e) { throw new RuntimeException(e); } } private void bootStrapProxy(M m) { if (proxy == null) { setProxy(m); if (modelImplObjects.isEmpty()){ List> modelImplClasses = getModelImplClasses(modelClass); for (Class implClass: modelImplClasses){ addModelImplObject(constructImpl(implClass, m)); } } } } @SuppressWarnings("unchecked") private static Object constructImpl(Class implClass, M m){ if (ModelImpl.class.isAssignableFrom(implClass)){ if (ModelImpl.class.equals(implClass)) { return new ModelImpl(m); }else { ParameterizedType pt = (ParameterizedType)implClass.getGenericSuperclass(); Class modelClass = (Class) pt.getActualTypeArguments()[0]; try { return implClass.getConstructor(modelClass).newInstance(m); } catch (Exception e) { throw new RuntimeException(e); } } } throw new RuntimeException("Don't know how to instantiate " + implClass.getName()); } private SequenceMap,Object> modelImplObjects = new SequenceMap,Object>(); private void addModelImplObject(Object o){ modelImplObjects.put(o.getClass(),o); } private Class getMethodImplClass(Method m){ try{ return methodImplClassCache.get(getReflector().getModelClass()).get(m); }catch(NullPointerException ex){ Config.instance().getLogger(getClass().getName()).log(Level.SEVERE, "Method" + m.getName() + ", ModelClass:"+ modelClass); throw ex; } } private static Cache,Cache>> methodImplClassCache = new Cache, Cache>>(0,0) { /** * */ private static final long serialVersionUID = -8303755398345923039L; @Override protected Cache> getValue(final Class modelClass) { return new Cache>(0,0) { /** * */ private static final long serialVersionUID = 1322249489351360016L; @Override protected Class getValue(Method method) { String mName = method.getName(); Class retType = method.getReturnType(); Class[] parameters = method.getParameterTypes(); for (Class implClass: getModelImplClasses(modelClass)){ try { Method inModelImplClass = implClass.getMethod(mName, parameters); if (retType.isAssignableFrom(inModelImplClass.getReturnType())){ return implClass; } }catch (NoSuchMethodException ex){ // } } return null; } }; } }; private static Cache,List>> modelImplClassesCache = new Cache, List>>(0,0) { /** * */ private static final long serialVersionUID = 7544606584634901930L; @Override protected List> getValue(Class modelClass) { SequenceSet> modelClasses = ModelReflector.instance(modelClass).getClassHierarchies(); List> modelImplClasses = new ArrayList>(); for (Class c : modelClasses){ String modelImplClassName = c.getName()+"Impl"; try { Class modelImplClass = Class.forName(modelImplClassName); if (ModelImpl.class.isAssignableFrom(modelImplClass)){ modelImplClasses.add(modelImplClass); }else { throw new ClassCastException(modelImplClassName + " does not extend " + ModelImpl.class.getName()); } }catch(ClassNotFoundException ex){ // Nothing } } return modelImplClasses; } }; private static List> getModelImplClasses(Class modelClass){ return modelImplClassesCache.get(modelClass); } public void save() { save(true); } public void save(boolean validate) { save(validate,false); } public void save(boolean validate,boolean dryRun) { if (!isDirty()) { return; } if (validate){ validate(); } beforeSave(); Record record = getRawRecord(); if (record.isNewRecord()) { callExtensions("before.create"); if (!dryRun){ create(); callExtensions("after.create"); } } else { callExtensions("before.update"); if (!dryRun){ update(); callExtensions("after.update"); } } if (!dryRun) { afterSave(); } } public void init(){ } private static final Cache>> _fieldValidators = new Cache>>(0,0) { /** * */ private static final long serialVersionUID = -8174150221673158116L; @Override protected List> getValue(String pool) { List> fieldValidators = new ArrayList>(); fieldValidators.add(new ExactLengthValidator(pool)); fieldValidators.add(new MaxLengthValidator(pool)); fieldValidators.add(new MinLengthValidator(pool)); fieldValidators.add(new NotNullValidator(pool)); fieldValidators.add(new RegExValidator(pool)); fieldValidators.add(new EnumerationValidator(pool)); fieldValidators.add(new DateFormatValidator(pool)); fieldValidators.add(new NumericRangeValidator(pool)); fieldValidators.add(new IntegerRangeValidator(pool)); return fieldValidators; } }; private static final List modelValidators = new ArrayList(); static{ modelValidators.add(new UniqueKeyValidator()); } protected boolean isModelValid(MultiException ex) { List fields = getReflector().getEditableFields(); boolean ret = true; for (String field : fields) { MultiException fieldException = new MultiException(); if (!getReflector().isHouseKeepingField(field) && !isFieldValid(field,fieldException)) { ex.add(fieldException); ret = false; } } if (ret){ for (ModelValidator v : modelValidators){ ret = v.isValid(getProxy(),ex) && ret; } } return ret; } protected boolean isFieldValid(String field, MultiException fieldException) { boolean ret = true; Iterator> i = _fieldValidators.get(getPool()).iterator(); while (i.hasNext()) { FieldValidator v = i.next(); ret = v.isValid(getProxy(), field, fieldException) && ret; } return ret; } protected void validate(){ beforeValidate(); MultiException me = new MultiException(); if (!isModelValid(me)) { throw me; } afterValidate(); } private SequenceSet getExtensionPoints(Class modelClass, String extnPointNameSuffix){ SequenceSet extnPoints = new SequenceSet(); ModelReflector ref = ModelReflector.instance(modelClass); for (Class inHierarchy : ref.getClassHierarchies()){ String extnPoint = inHierarchy.getSimpleName() + "." + extnPointNameSuffix; extnPoints.add(extnPoint); } return extnPoints; } private void callExtensions(String extnPointNameSuffix){ for (String extnPoint: getExtensionPoints(getReflector().getModelClass(), extnPointNameSuffix)){ Registry.instance().callExtensions(extnPoint, getProxy()); } } public void preValidate(){ beforeValidate(); } protected void beforeValidate(){ defaultFields(); callExtensions("before.validate"); } public void defaultFields(){ Record record = getRawRecord(); if (!record.isNewRecord()){ ColumnDescriptor updatedAt = getReflector().getColumnDescriptor("updated_at"); ColumnDescriptor updatorUser = getReflector().getColumnDescriptor("updater_user_id"); if (!updatedAt.isVirtual()){ proxy.setUpdatedAt(null); } if (!updatorUser.isVirtual()){ proxy.setUpdaterUserId(null); } } ModelReflector reflector = getReflector(); for (String field:reflector.getRealFields()){ String columnName = reflector.getColumnDescriptor(field).getName(); if (record.get(columnName) == null){ Method fieldGetter = reflector.getFieldGetter(field); COLUMN_DEF cdef = reflector.getAnnotation(fieldGetter,COLUMN_DEF.class); if (cdef != null){ Object defaultValue = StandardDefaulter.getDefaultValue(cdef.value(),cdef.args(),reflector.getTimeZone()); record.put(columnName,defaultValue); } } } } protected void afterValidate(){ callExtensions("after.validate"); } protected void beforeSave() { callExtensions("before.save"); } protected void afterSave() { callExtensions("after.save"); } protected void beforeDestory(){ callExtensions("before.destroy"); } protected void afterDestroy(){ callExtensions("after.destroy"); } public boolean isBeingDestroyed(){ return beingDestroyed; } private boolean beingDestroyed = false; private void destroyCascade(){ ModelReflector ref = getReflector(); for (Method childrenGetter : ref.getChildGetters()){ Class childModelClass = ref.getChildModelClass(childrenGetter); ModelReflector childReflector = ModelReflector.instance(childModelClass); List referenceFields = childReflector.getReferenceFields(ref.getModelClass()); if (ref.isAnnotationPresent(childrenGetter,IS_VIRTUAL.class)){ continue; } for (String referenceField: referenceFields){ try { if (childReflector.getRealModelClass() == null){ continue; } if (childReflector.isFieldVirtual(referenceField)){ continue; } @SuppressWarnings("unchecked") List children = (List)childrenGetter.invoke(getProxy()); for (Model child : children){ if (childReflector.isFieldMandatory(referenceField)){ child.destroy(); }else { childReflector.set(child,referenceField,null); child.save(); } } } catch (Exception e) { throw new RuntimeException(e); } } } } public void destroy() { if (isBeingDestroyed()){ return; } try { beingDestroyed = true; beforeDestory(); destroyCascade(); Delete q = new Delete(getReflector()); Expression condition = new Expression(getPool(),Conjunction.AND); condition.add(new Expression(getPool(),getReflector().getColumnDescriptor("id").getName(),Operator.EQ,new BindVariable(getPool(),proxy.getId()))); condition.add(new Expression(getPool(),getReflector().getColumnDescriptor("lock_id").getName(),Operator.EQ,new BindVariable(getPool(),proxy.getLockId()))); q.where(condition); if (q.executeUpdate() <= 0){ throw new RecordNotFoundException(); } Database.getInstance().getCache(getReflector()).registerDestroy((Model)getProxy()); Database.getInstance().getCurrentTransaction().registerTableDataChanged(getReflector().getTableName()); afterDestroy(); }finally{ beingDestroyed = false; } } private void update() { Record record = getRawRecord(); Set dirtyFields = new HashSet<>(record.getDirtyFields()); encrypt(); int oldLockId = proxy.getLockId(); int newLockId = oldLockId + 1; Update q = new Update(getReflector()); Iterator fI = dirtyFields.iterator(); while (fI.hasNext()) { String columnName = fI.next(); String fieldName = getReflector().getFieldName(columnName); if (getReflector().isFieldVirtual(fieldName)){ continue; } TypeRef ref = Database.getJdbcTypeHelper(getPool()).getTypeRef(getReflector().getFieldGetter(fieldName).getReturnType()); q.set(columnName,new BindVariable(getPool(),record.get(columnName), ref)); } String idColumn = getReflector().getColumnDescriptor("id").getName(); Expression condition = new Expression(getPool(),Conjunction.AND); condition.add(new Expression(getPool(),idColumn,Operator.EQ,new BindVariable(getPool(),proxy.getId()))); ColumnDescriptor lockIdColumDescriptor = getReflector().getColumnDescriptor("lock_id"); if (!lockIdColumDescriptor.isVirtual()){ String lockidColumn = lockIdColumDescriptor.getName(); q.set(lockidColumn,new BindVariable(getPool(),newLockId)); condition.add(new Expression(getPool(),lockidColumn,Operator.EQ,new BindVariable(getPool(),oldLockId))); } q.where(condition); if (q.executeUpdate() <= 0){ throw new RecordNotFoundException(); } decrypt(); proxy.setLockId(newLockId); record.startTracking(); if (!getReflector().isAnnotationPresent(CONFIGURATION.class)){ record.setLocked(true); //Do only for transaction tables as config cache would need to be reset to false after commit. This is just to avoid that unwanted loop over config records cached. } Database.getInstance().getCache(getReflector()).registerUpdate((Model)getProxy()); Database.getInstance().getCurrentTransaction().registerTableDataChanged(getReflector().getTableName()); } private void encrypt(){ List encryptedFields = getReflector().getEncryptedFields(); if (encryptedFields.isEmpty()){ return; } for (String f: encryptedFields){ String value = getReflector().get(proxy,f); if (getRawRecord().isFieldDirty(f) && !getReflector().isVoid(value)){ getReflector().set(proxy,f, SharedKeys.getInstance().encrypt(value)); } } } private void decrypt(){ List encryptedFields = getReflector().getEncryptedFields(); if (encryptedFields.isEmpty()){ return; } for (String f: encryptedFields){ String value = getReflector().get(proxy,f); if (getRawRecord().isFieldDirty(f) && !getReflector().isVoid(value)) { getReflector().set(proxy, f, SharedKeys.getInstance().decrypt(value)); } } } private void create() { encrypt(); Record record = getRawRecord(); proxy.setLockId(0); //Table table = Database.getTable(getReflector().getTableName()); Insert insertSQL = new Insert(getReflector()); Map values = new HashMap(); Iterator columnIterator = record.getDirtyFields().iterator(); while (columnIterator.hasNext()) { String columnName = columnIterator.next(); String fieldName = getReflector().getFieldName(columnName); if (fieldName == null || getReflector().isFieldVirtual(fieldName)){ continue; } TypeRef ref = Database.getJdbcTypeHelper(getPool()).getTypeRef(getReflector().getFieldGetter(fieldName).getReturnType()); values.put(columnName,new BindVariable(getPool(),record.get(columnName), ref)); } insertSQL.values(values); Record generatedValues = new Record(getPool()); Set autoIncrementColumns = getReflector().getAutoIncrementColumns(); assert (autoIncrementColumns.size() <= 1); // atmost one auto increment id column List generatedKeys = new ArrayList(); for (String anAutoIncrementColumn:autoIncrementColumns){ if ( Database.getJdbcTypeHelper(getPool()).isColumnNameAutoLowerCasedInDB() ){ generatedKeys.add(LowerCaseStringCache.instance().get(anAutoIncrementColumn)); }else { generatedKeys.add(anAutoIncrementColumn); } } insertSQL.executeUpdate(generatedValues, generatedKeys.toArray(new String[]{})); if (generatedKeys.size() == 1){ if (generatedValues.getFieldNames().size() == 1){ String virtualFieldName = generatedValues.getFieldNames().iterator().next(); long id = ((Number)generatedValues.get(virtualFieldName)).longValue(); String fieldName = generatedKeys.get(0); record.put(fieldName, id); } } decrypt(); record.setNewRecord(false); record.startTracking(); if (!getReflector().isAnnotationPresent(CONFIGURATION.class)){ record.setLocked(true); } Database.getInstance().getCache(getReflector()).registerInsert((Model)getProxy()); Database.getInstance().getCurrentTransaction().registerTableDataChanged(getReflector().getTableName()); } @Override public boolean equals(Object o){ if (o == null){ return false; } if (!(o instanceof ModelInvocationHandler) && !getReflector().canReflect(o)){ return false; } if (o instanceof ModelInvocationHandler){ return equalImpl((ModelInvocationHandler)o); }else { return equalsProxy((Model)o); } } public int hashCode(){ return (getModelName() + ":" + getProxy().getId()).hashCode() ; } protected boolean equalImpl(ModelInvocationHandler anotherImpl){ return (getProxy().getId() == anotherImpl.getProxy().getId()) && getReflector().getTableName().equals(anotherImpl.getReflector().getTableName()); } protected boolean equalsProxy(Model anotherProxy){ boolean ret = false; if (anotherProxy != null){ ret = getProxy().getId() == anotherProxy.getId(); } return ret; } @SuppressWarnings("unchecked") public M cloneProxy(){ return (M)getRawRecord().clone().getAsProxy(getReflector().getModelClass()); } private transient Map txnProperties = new HashMap(); public Object getTxnProperty(String name) { return txnProperties.get(name); } public void setTxnProperty(String name,Object value) { txnProperties.put(name, value); } public Object removeTxnProperty(String name) { return txnProperties.remove(name); } public boolean isDirty(){ return !getProxy().getRawRecord().getDirtyFields().isEmpty(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy