Package com.mobixess.jodb.core.transaction

Source Code of com.mobixess.jodb.core.transaction.BaseProcessor

/*
Copyright (C) 2007  Mobixess Inc. http://www.java-objects-database.com

This file is part of the JODB (Java Objects Database) open source project.

JODB is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation.

JODB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package com.mobixess.jodb.core.transaction;

import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.BitSet;

import com.mobixess.jodb.core.IllegalClassTypeException;
import com.mobixess.jodb.core.JODBConfig;
import com.mobixess.jodb.core.JodbIOException;
import com.mobixess.jodb.core.JODBConstants.COMPARE_RESULT;
import com.mobixess.jodb.core.io.IOBase;
import com.mobixess.jodb.core.io.JODBOperationContext;
import com.mobixess.jodb.core.io.ObjectDataContainer;
import com.mobixess.jodb.core.io.ObjectDataContainer.FieldRecord;
import com.mobixess.jodb.core.io.ObjectDataContainer.FieldsIterator;
import com.mobixess.jodb.core.plugin.IClassProcessor;
import com.mobixess.jodb.core.transaction.JODBSession.ClassDescriptor;
import com.mobixess.jodb.core.transaction.JODBSession.FieldAndIDRecord;
import com.mobixess.jodb.core.transaction.TransactionUtils.DataContainersCache;
import com.mobixess.jodb.util.ArrayUtils;
import com.mobixess.jodb.util.PrimitiveJavaTypesUtil;
import com.mobixess.jodb.util.PrimitiveJavaTypesUtil.PRIMITIVES_ENUMERATION;

public class BaseProcessor implements IClassProcessor {

    public COMPARE_RESULT compare(Object value1, Object value2, JODBOperationContext context, Field[] fieldsToIgnore) {
        if(equals(value1, value2, context, fieldsToIgnore)){
            return COMPARE_RESULT.EQUAL;
        }
        return COMPARE_RESULT.UNKNOWN;
    }

    public COMPARE_RESULT compare(Object value1, ObjectDataContainer value2,
            JODBOperationContext context, Field[] fieldsToIgnore, Class originalClass) throws IOException
    {
        if(equals(value1, value2, context, fieldsToIgnore)){
            return COMPARE_RESULT.EQUAL;
        }
        return COMPARE_RESULT.UNKNOWN;
    }

    public Object composeInstance(Class type,
            ObjectDataContainer persistentDataContainer, JODBSession session) throws IOException
    {
        ClassDescriptor classDescriptor;

        classDescriptor = session.getDescriptorForClass(type);


        if (persistentDataContainer.isArray()) {
            return Array.newInstance(type, persistentDataContainer.getActiveFieldsIterator().getRemainingInCurrentCategory());
        }
           
        try {
            return classDescriptor.newInstance();
        } catch (IllegalClassTypeException e) {
            throw new JodbIOException(e);
        }
    }

    public boolean equals(Object value1, Object value2, JODBOperationContext context, Field[] fieldsToIgnore) {
        if(value1 == value2){
            return true;
        }
        if(value1 == null || value2 == null){
            return false;
        }
        if(value1.getClass()!=value2.getClass()){
            return false;
        }
        if(value1.getClass().isArray()){
            return arraysAreEqual(value1, value2, context, fieldsToIgnore);
        }else{
            return objectsAreEqual(value1, value2, context, fieldsToIgnore);
        }
    }
   
    private boolean objectsAreEqual(Object value1, Object value2, JODBOperationContext context, Field[] fieldsToIgnore) {
        ClassDescriptor classDescriptor = context.getSession().getDescriptorForClass(value1.getClass());

        FieldAndIDRecord[] fields = classDescriptor.getAllFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i]._field;
            if(ArrayUtils.indexOf(fieldsToIgnore, field)!=-1 ){
                continue;
            }
            try {
                Object val1 = field.get(value1);
                Object val2 = field.get(value2);
                if(val1 == val2 || (field.getType().isPrimitive() && val1.equals(val2))){
                    continue;
                }
                if(val1!=null && (val1.getClass()==String.class) && val1.equals(val2)){
                    continue;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
       
        return true;
    }
   
    public boolean arraysAreEqual(Object value1, Object value2, JODBOperationContext context, Field[] fieldsToIgnore) {
        int size1 = Array.getLength(value1);
        int size2 = Array.getLength(value2);
        if(size1!=size2){
            return false;
        }
        boolean isPrimitive = value1.getClass().getComponentType().isPrimitive();
        for (int i = 0; i < size1; i++) {
            Object val1 = Array.get(value1, i);
            Object val2 = Array.get(value2, i);
            if(isPrimitive){
                if(!val1.equals(val2)){
                    return false;
                }
            }else{
                if(val1!=val2){
                    return false;
                }
            }
        }
        return false;
    }

    public boolean equals(Object value1, ObjectDataContainer value2,
            JODBOperationContext context, Field[] fieldsToIgnore) throws IOException
    {
        ClassDescriptor desc;
        try {
            desc = context.getSession().getDescriptorForClass(value1.getClass());
            if (desc.isArray()) {
                return checkActiveArrayObjectUnchanged(context, value1, value2, desc);
            }
        } catch (IllegalClassTypeException e) {
            e.printStackTrace();
            throw new JodbIOException(e);
        }
        return equalToPersistentCopy(context, value1, value2, desc, fieldsToIgnore);
    }

    public Object translate(Object objectToTranslate) {
        return objectToTranslate;
    }

    public Class getType() {
        return Object.class;
    }

    public void activate(Object incompleteInstance, ObjectDataContainer persistentDataContainer, JODBSession session, int activationDepth, boolean delayedActivation) throws IOException {
        if(persistentDataContainer.isArray()){
            fillArray(session, delayedActivation, persistentDataContainer,  incompleteInstance, activationDepth);
        }else{
            fillObject(session, delayedActivation, persistentDataContainer,  incompleteInstance, activationDepth);
        }
    }


    private static void fillObject(JODBSession session, boolean delayedActivation, ObjectDataContainer objectDataContainer,  Object instance, int remainingDepth) throws IOException{
        ClassDescriptor classDescriptor = session.getDescriptorForClass(instance.getClass());

        IOBase base = session.getBase();
        FieldsIterator fieldsIterator = objectDataContainer.getActiveFieldsIterator();
        if(fieldsIterator == null){
            return;
        }
        BitSet processedFieldMask = new BitSet();
        FieldRecord record = objectDataContainer.getRecordCache();
        for (int i = 0; fieldsIterator.hasNext(); i++) {
            fieldsIterator.next(record, base);
            Field field = classDescriptor.getFieldForID(record._fieldID, processedFieldMask);
            if (field == null) {
                continue;
            }
            if (field.getType().isPrimitive() && !delayedActivation) {
                try {
                    field.set(instance, record._value);
                } catch (Exception e) {
                    setDefaultValue(instance, field);
                    //TODO add debug level output
                }
                continue;
            }
            if (remainingDepth < 1) {
                continue;
            }
            Object child = TransactionUtils.launchObject(session, record._objectOffset, null, remainingDepth - 1);
            try {
                if(child!=null || JODBConfig.isAllowNullInReflectionSet()){
                    field.set(instance, child);
                }
            } catch (Exception e) {
                setDefaultValue(instance, field);
                //TODO add debug level output
                continue;
            }
        }
        if (!delayedActivation) {
            FieldAndIDRecord[] fields = classDescriptor.getAllFields();
            for (int i = 0; i < fields.length; i++) {//set default values for remaining fields
                if (processedFieldMask.get(i)) {
                    continue;
                }
                setDefaultValue(instance, fields[i]._field);
            }
        }       
    }

    private static void fillArray(JODBSession session,
            boolean activation, ObjectDataContainer objectDataContainer,
            Object instance, int remainingDepth) throws IOException
    {
        IOBase base = session.getBase();
        FieldsIterator fieldsIterator = objectDataContainer.getActiveFieldsIterator();
        if(fieldsIterator == null){
            return;
        }
        FieldRecord record = objectDataContainer.getRecordCache();
        ClassDescriptor arrayTypeDescriptor;

        arrayTypeDescriptor = session.getDescriptorForClass(instance.getClass().getComponentType());

        if (arrayTypeDescriptor.isPrimitive()) {
            for (int i = 0; fieldsIterator.hasNext(); i++) {
                fieldsIterator.next(record, base);
                Array.set(instance, i, record._value);
            }
        } else {
            for (int i = 0; fieldsIterator.hasNext(); i++) {
                fieldsIterator.next(record, base);
                Object child = TransactionUtils.launchObject(session,  record._objectOffset, null, remainingDepth - 1);
                Array.set(instance, i, child);
            }
        }
    }

   
    private static void setDefaultValue(Object obj,Field field){
        try {
            Class type = field.getType();
            if(type.isPrimitive()){
                Object value = PrimitiveJavaTypesUtil.getDefaultWrapperInstance(type.getName());
                field.set(obj, value);
            }else{
                if(JODBConfig.isAllowNullInReflectionSet()){
                    field.set(obj, null);
                }
            }
        } catch (Exception e) {
            //TODO print for debug?
        }
    }

    private static boolean equalToPersistentCopy(JODBOperationContext context, Object currentObject, ObjectDataContainer persistentCopyObjectDataContainer, ClassDescriptor desc , Field[] fieldsToIgnore) throws IOException{
        //Field[] fields = desc.getFields();
        JODBSession session = context.getSession();
        //int[] fieldsIDs = desc.getFieldsSubstitutionIDs();
        //boolean[] processedFields = new boolean[fieldsIDs.length];
        FieldRecord fieldRecord = persistentCopyObjectDataContainer.getRecordCache();
        FieldsIterator fieldsIterator = persistentCopyObjectDataContainer.getActiveFieldsIterator();
        if(fieldsIterator == null){
            return false;
        }
        while (fieldsIterator.hasNext()) {
            fieldsIterator.next(fieldRecord, context.getBase(),false);
//            int index = ArrayUtils.indexOf(fieldsIDs, fieldRecord._fieldID);
//            if(index == -1){
//                continue;//TODO the field is not exist anymore, should it indicate as "not equal" ?
//            }
            Field field = desc.getFieldForID(fieldRecord._fieldID, null);
            if(field == null){
                continue;//TODO the field is not exist anymore, should it indicate as "not equal" ?
            }
//            if( fieldsToIgnore!=null && ArrayUtils.indexOf(fieldsToIgnore, field)!=-1){
//                processedFields[index] = true;
//                continue;
//            }
            Object value;
            try {
                value = field.get(currentObject);
            } catch (Exception e) {
                throw new JodbIOException(e);
            }
            if(field.getType().isPrimitive()){
                if( PrimitiveJavaTypesUtil.comparePrimitives(value, fieldRecord._primitiveRawDataBuffer) != 0 ){
                    return false;
                }
            }else{
                if(value == null){//if object under the persistent offset is delete than we continue itteration
                    if(fieldRecord._objectOffset != 0){
                        DataContainersCache dataContainersCache = TransactionUtils.getObjectDataContainerCache();
                        ObjectDataContainer referencedObjectDataContainer =  dataContainersCache.pullObjectDataContainer();
                        try {
                            referencedObjectDataContainer.readHeader(context.getIoTicket().getRandomAccessBuffer(), fieldRecord._objectOffset, true);
                            if(!referencedObjectDataContainer.isDeleted()){
                                return false;
                            }
                        } finally {
                            dataContainersCache.pushObjectDataContainer(referencedObjectDataContainer);
                        }
                    }
                }else{
                    PersistentObjectHandle objectHandle = session.getHandleForActiveObject(value);
                    if(objectHandle == null || objectHandle.getObjectEntryOffset() != fieldRecord._objectOffset){
                        return false;
                    }
                }                   
            }
            //processedFields[index] = true;
        }
   
//      TODO commented because iterrator now guarantee iterration through all field
//        for (int i = 0; i < fieldsIDs.length; i++) {//cheking if remaining not found fields have default values
//            if(fieldsIDs[i]==-1||processedFields[i]){
//                continue;
//            }
//            Field field = fields[i];
//            if(field.getType().isPrimitive()){
//                if(!Utils.primitiveEquals(field, currentObject, 0)){
//                    return false;
//                }
//            }else{
//                Object value;
//                try {
//                    value = field.get(currentObject);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    throw new IOException(e.getMessage());
//                }
//                if(value!=null){
//                    return false;
//                }
//            }
//        }
        return true;
    }

    private static boolean checkActiveArrayObjectUnchanged(JODBOperationContext context, Object array, ObjectDataContainer objectDataContainer, ClassDescriptor classDescriptor) throws IOException, IllegalClassTypeException{
        //TODO make size estimation here?
        int arraySize = Array.getLength(array);
        FieldsIterator fieldsIterator = objectDataContainer.getActiveFieldsIterator();
        if(fieldsIterator  == null){
            return false;//TODO add warning?
        }
        if(arraySize!=fieldsIterator.getRemainingInCurrentCategory()){
            return true;
        }
        IOBase base = context.getBase();
        JODBSession session = context.getSession();
        FieldRecord fieldRecord = objectDataContainer.getRecordCache();
        if( !classDescriptor.getArrayType().isPrimitive()  ){
            for (int i = 0; i < arraySize; i++) {
                fieldsIterator.next(fieldRecord, base);
                Object value = Array.get(array, i);
                if(value == null){
                    if(fieldRecord._objectOffset!=0){
                        return false;
                    }
                    continue;
                }
                PersistentObjectHandle handle = session.getHandleForActiveObject(value);
                if(handle == null || handle.getObjectEntryOffset() != fieldRecord._objectOffset){
                    return false;
                }
            }
        }else{
            PRIMITIVES_ENUMERATION enumeratedPrimitiveType = PrimitiveJavaTypesUtil.getEnumeratedType(classDescriptor.getArrayType().getName());
            for (int i = 0; i < arraySize; i++) {
                fieldsIterator.next(fieldRecord, base, false);
                Object value = Array.get(array, i);
                if( PrimitiveJavaTypesUtil.comparePrimitives(value, enumeratedPrimitiveType, fieldRecord._primitiveRawDataBuffer) != 0 ){
                    return false;
                }
            }
        }
        return true;
    }

    public int getUsageCondition() {
        throw new RuntimeException("Not Implemented");
    }

    public boolean acceptType(Class typeOfObjectToProcess) {
        return true;
    }
}
TOP

Related Classes of com.mobixess.jodb.core.transaction.BaseProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.