private void addEqualsMethod(int equalityType) {
        TypeDesc[] objectParam = {TypeDesc.OBJECT};

        String equalsMethodName;
        switch (equalityType) {
        default:
            throw new IllegalArgumentException();
        case EQUAL_KEYS:
            equalsMethodName = EQUAL_PRIMARY_KEYS_METHOD_NAME;
            break;
        case EQUAL_PROPERTIES:
            equalsMethodName = EQUAL_PROPERTIES_METHOD_NAME;
            break;
        case EQUAL_FULL:
            equalsMethodName = EQUALS_METHOD_NAME;
        }

        Modifiers modifiers = Modifiers.PUBLIC.toSynchronized(true);
        MethodInfo mi = addMethodIfNotFinal
            (modifiers, equalsMethodName, TypeDesc.BOOLEAN, objectParam);

        if (mi == null) {
            return;
        }

        CodeBuilder b = new CodeBuilder(mi);

        // if (this == target) return true;
        b.loadThis();
        b.loadLocal(b.getParameter(0));
        Label notEqual = b.createLabel();
        b.ifEqualBranch(notEqual, false);
        b.loadConstant(true);
        b.returnValue(TypeDesc.BOOLEAN);
        notEqual.setLocation();

        // FIXME: Using instanceof means that equals is not symmetric.
        // if (! target instanceof this) return false;
        TypeDesc userStorableTypeDesc = TypeDesc.forClass(mStorableType);
        b.loadLocal(b.getParameter(0));
        b.instanceOf(userStorableTypeDesc);
        Label fail = b.createLabel();
        b.ifZeroComparisonBranch(fail, "==");

        // this.class other = (this.class)target;
        LocalVariable other = b.createLocalVariable(null, userStorableTypeDesc);
        b.loadLocal(b.getParameter(0));
        b.checkCast(userStorableTypeDesc);
        b.storeLocal(other);

        for (StorableProperty property : mAllProperties.values()) {
            if (property.isDerived() || property.isJoin()) {
                continue;
            }
            // If we're only comparing keys, and this isn't a key, skip it
            if ((equalityType == EQUAL_KEYS) && !property.isPrimaryKeyMember()) {
                continue;
            }

            // Check if independent property is supported, and skip if not.
            Label skipCheck = b.createLabel();
            if (equalityType != EQUAL_KEYS && property.isIndependent()) {
                addSkipIndependent(b, other, property, skipCheck);
            }

            TypeDesc fieldType = TypeDesc.forClass(property.getType());
            loadThisProperty(b, property);

            b.loadLocal(other);
            b.invoke(property.getReadMethod());
            CodeBuilderUtil.addValuesEqualCall(b, fieldType, true, fail, false);

            skipCheck.setLocation();
        }

        b.loadConstant(true);
        b.returnValue(TypeDesc.BOOLEAN);

        fail.setLocation();
        b.loadConstant(false);
        b.returnValue(TypeDesc.BOOLEAN);
    }
private void addEqualsMethod ( int equalityType ) { TypeDesc [ ] objectParam = { TypeDesc . OBJECT } ; String equalsMethodName ; switch ( equalityType ) { default : throw new IllegalArgumentException ( ) ; case EQUAL_KEYS : equalsMethodName = EQUAL_PRIMARY_KEYS_METHOD_NAME ; break ; case EQUAL_PROPERTIES : equalsMethodName = EQUAL_PROPERTIES_METHOD_NAME ; break ; case EQUAL_FULL : equalsMethodName = EQUALS_METHOD_NAME ; } Modifiers modifiers = Modifiers . PUBLIC . toSynchronized ( true ) ; MethodInfo mi = addMethodIfNotFinal ( modifiers , equalsMethodName , TypeDesc . BOOLEAN , objectParam ) ; if ( mi == null ) { return ; } CodeBuilder b = new CodeBuilder ( mi ) ; b . loadThis ( ) ; b . loadLocal ( b . getParameter ( 0 ) ) ; Label notEqual = b . createLabel ( ) ; b . ifEqualBranch ( notEqual , false ) ; b . loadConstant ( true ) ; b . returnValue ( TypeDesc . BOOLEAN ) ; notEqual . setLocation ( ) ; TypeDesc userStorableTypeDesc = TypeDesc . forClass ( mStorableType ) ; b . loadLocal ( b . getParameter ( 0 ) ) ; b . instanceOf ( userStorableTypeDesc ) ; Label fail = b . createLabel ( ) ; b . ifZeroComparisonBranch ( fail , "==" ) ; LocalVariable other = b . createLocalVariable ( null , userStorableTypeDesc ) ; b . loadLocal ( b . getParameter ( 0 ) ) ; b . checkCast ( userStorableTypeDesc ) ; b . storeLocal ( other ) ; for ( StorableProperty property : mAllProperties . values ( ) ) { if ( property . isDerived ( ) || property . isJoin ( ) ) { continue ; } if ( ( equalityType == EQUAL_KEYS ) && ! property . isPrimaryKeyMember ( ) ) { continue ; } Label skipCheck = b . createLabel ( ) ; if ( equalityType != EQUAL_KEYS && property . isIndependent ( ) ) { addSkipIndependent ( b , other , property , skipCheck ) ; } TypeDesc fieldType = TypeDesc . forClass ( property . getType ( ) ) ; loadThisProperty ( b , property ) ; b . loadLocal ( other ) ; b . invoke ( property . getReadMethod ( ) ) ; CodeBuilderUtil . addValuesEqualCall ( b , fieldType , true , fail , false ) ; skipCheck . setLocation ( ) ; } b . loadConstant ( true ) ; b . returnValue ( TypeDesc . BOOLEAN ) ; fail . setLocation ( ) ; b . loadConstant ( false ) ; b . returnValue ( TypeDesc . BOOLEAN ) ; }
Defines an equals method.

@param equalityType Type of equality to define - {@link EQUAL_KEYS} for "equalKeys",
{@link EQUAL_PROPERTIES} for "equalProperties", and {@link EQUAL_FULL} for "equals"