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

org.boon.criteria.Criterion Maven / Gradle / Ivy

Go to download

Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!

There is a newer version: 0.34
Show newest version
package org.boon.criteria;

import org.boon.Exceptions;
import org.boon.core.Typ;
import org.boon.core.Conversions;
import org.boon.core.reflection.fields.FieldAccess;
import org.boon.primitive.CharBuf;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

import static org.boon.Boon.sputl;
import static org.boon.Boon.sputs;


public abstract class Criterion extends Criteria {

    private String name;
    private Operator operator;
    protected VALUE value;
    protected VALUE[] values;
    private final int hashCode;
    private final String toString;

    private boolean initialized;
    private Criterion nativeDelegate;
    private boolean useDelegate;

    private FieldAccess field;

    private Object objectUnderTest;

    private Map fields;

    public Criterion( String name, Operator operator, VALUE... values ) {
        Objects.requireNonNull( name, "name cannot be null" );
        Objects.requireNonNull( operator, "operator cannot be null" );
        Objects.requireNonNull( values, "values cannot be null" );

        this.name = name;
        this.operator = operator;
        this.setValues( values );
        hashCode = doHashCode();
        toString = doToString();
    }


    public String getName() {
        return name;
    }

    public Operator getOperator() {
        return operator;
    }


    public VALUE getValue() {
        return value;
    }


    public VALUE[] getValues() {
        return values;
    }

    public void setValues( VALUE[] values ) {
        if ( values.length > 0 ) {
            this.value = values[ 0 ];
        }
        this.values = values;
    }


    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( !( o instanceof Criterion ) ) return false;

        Criterion criterion = ( Criterion ) o;

        if ( name != null ? !name.equals( criterion.name ) : criterion.name != null ) return false;
        if ( operator != criterion.operator ) return false;
        if ( value != null ? !value.equals( criterion.value ) : criterion.value != null ) return false;
        if ( !Arrays.equals( values, criterion.values ) ) return false;

        return true;
    }


    @Override
    public int hashCode() {
        return hashCode;
    }

    public int doHashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + ( operator != null ? operator.hashCode() : 0 );
        result = 31 * result + ( value != null ? value.hashCode() : 0 );
        result = 31 * result + ( values != null ? Arrays.hashCode( values ) : 0 );
        return result;
    }

    @Override
    public String toString() {
        return toString;
    }


    public String doToString() {
        CharBuf builder = CharBuf.create( 80 );
        builder.add( "c{" );
        builder.add( "\"name\":'" );
        builder.add( String.valueOf( name ) );
        builder.add( ", \"operator\":" );
        builder.add( String.valueOf( operator ) );
        builder.add( ", \"set\":" );
        builder.add( String.valueOf( value ) );
        builder.add( ", \"update\":" );
        builder.add( Arrays.toString( values ) );
        builder.add( "}" );
        return builder.toString();
    }

    public boolean isInitialized() {
        return initialized;
    }


    public void initByClass( Class clazz ) {

        this.fields = getFieldsInternal( clazz );
        initIfNeeded();
    }

    public void initByFields( Map fields ) {
        this.fields = fields;
        initIfNeeded();
    }


    //Only called when part of group.
    public void prepareForGroupTest( Map fields, Object owner ) {

        this.fields = fields;
        this.objectUnderTest = owner;


    }

    public void cleanAfterGroupTest() {
        clean();
    }

    public void clean() {
        this.field = null;
        this.fields = null;
        this.objectUnderTest = null;

    }

    @Override
    public boolean test( Object o ) {


        try {

            Objects.requireNonNull( o, "object under test can't be null" );

            this.objectUnderTest = o;

            initIfNeeded();
            if ( this.useDelegate ) {

                return this.nativeDelegate.resolve( fields, o );
            }


            boolean result = resolve( fields, o );

            return result;

        } catch ( Exception ex ) {
            return Exceptions.handle( Typ.bool,
                    sputl( "In class " + this.getClass().getName(),
                            "the test method is unable to test the following criteria operator",
                            Objects.toString( this.getOperator() ),
                            sputs( "The field name is          :          ", this.getName() ),
                            sputs( "The value is               :          ", this.getValue() ),
                            sputs( "The value type is          :          ", this.getValue().getClass().getName() ),
                            sputs( "The object under test      :          ", this.objectUnderTest ),
                            sputs( "The object under test type :          ",
                                    this.objectUnderTest == null ? "null" : this.objectUnderTest.getClass().getName() ),
                            sputs( "Field                      :          ",
                                    field ),
                            sputs( "Fields                     :          ",
                                    fields ),

                            sputs()

                    )
                    , ex );
        }
    }

    private FieldAccess field() {
        if ( field == null ) {
            field = fields().get( this.name );
        }
        return field;
    }

    private Map fields() {

        if ( fields == null ) {
            fields = getFieldsInternal( this.objectUnderTest );
        }
        return fields;
    }

    public static abstract class PrimitiveCriterion extends Criterion {

        public PrimitiveCriterion( String name, Operator operator, Object... objects ) {
            super( name, operator, objects );
        }

        @Override
        public boolean test( Object o ) {

            Map fields = getFieldsInternal( o );
            return resolve( fields, o );
        }

    }


    private void initForShortValue( short v ) {

        this.value = ( VALUE ) ( Short ) v;

        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqShort( name, v );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqShort( name, v );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltShort( name, v );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteShort( name, v );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtShort( name, v );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteShort( name, v );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inShorts( name, Conversions.sarray( values ) );
                break;


            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenShort( name, ( v ),
                        Conversions.toShort( values[ 1 ] ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInShorts( name, Conversions.sarray( values ) );

                break;

            default:
                useDelegate = false;
        }
    }


    private void initIfNeeded() {

        if ( initialized ) return;
        initialized = true;

        FieldAccess field = field();
        if ( field == null ) {
            return;
        }

        Class type = field.getType();


        if ( !type.isPrimitive() && type != Typ.date ) {
            return;
        }


        if ( type == Typ.date ) {

            if ( !( value instanceof Date ) ) {
                initForDate();
            }
            return;
        }


        useDelegate = true;


        if ( type == Typ.intgr ) {
            int v = Conversions.toInt( value );
            initForInt( v );
        } else if ( type == Typ.bt ) {

            byte v = Conversions.toByte( value );

            initForByte( v );

        } else if ( type == Typ.shrt ) {

            short v = Conversions.toShort( value );

            initForShortValue( v );

        } else if ( type == Typ.lng ) {

            long v = Conversions.toLong( value );

            initForLong( v );


        } else if ( type == Typ.flt ) {

            float v = Conversions.toFloat( value );


            initForFloat( v );

        } else if ( type == Typ.dbl ) {

            double v = Conversions.toDouble( value );

            initForDouble( v );


        } else if ( type == Typ.bln ) {


            switch ( operator ) {
                case EQUAL:
                    nativeDelegate = CriteriaFactory.eqBoolean( name, Conversions.toBoolean( value ) );
                    break;

                case NOT_EQUAL:
                    nativeDelegate = CriteriaFactory.notEqBoolean( name, Conversions.toBoolean( value ) );
                    break;


                default:
                    useDelegate = false;
            }

        } else if ( type == Typ.chr ) {

            char v = Conversions.toChar( value );
            initForChar( v );

        }


    }

    private void initForChar( char value ) {


        this.value = ( VALUE ) ( Character ) value;

        switch ( operator ) {


            case EQUAL:
                nativeDelegate = CriteriaFactory.eqChar( name, ( value ) );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqChar( name, ( value ) );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltChar( name, ( value ) );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteChar( name, ( value ) );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtChar( name, ( value ) );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteChar( name, ( value ) );
                break;

            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenChar( name, ( value ),
                        Conversions.toChar( values[ 1 ] ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inChars( name, Conversions.carray( values ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInChars( name, Conversions.carray( values ) );
                break;

            default:
                useDelegate = false;
        }
    }

    private void initForDouble( double value ) {

        this.value = ( VALUE ) ( Double ) value;

        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqDouble( name, ( value ) );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqDouble( name, ( value ) );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltDouble( name, ( value ) );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteDouble( name, ( value ) );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtDouble( name, ( value ) );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteDouble( name, ( value ) );
                break;

            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenDouble( name, ( value ),
                        Conversions.toDouble( values[ 1 ] ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inDoubles( name,
                        Conversions.darray( values ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInDoubles( name,
                        Conversions.darray( values ) );
                break;

            default:
                useDelegate = false;
        }
    }

    private void initForFloat( float value ) {

        this.value = ( VALUE ) ( Float ) value;

        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqFloat( name, ( value ) );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqFloat( name, ( value ) );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltFloat( name, ( value ) );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteFloat( name, ( value ) );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtFloat( name, ( value ) );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteFloat( name, ( value ) );
                break;

            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenFloat( name, ( value ),
                        Conversions.toFloat( values[ 1 ] ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inFloats( name, Conversions.farray( values ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInFloats( name, Conversions.farray( values ) );

                break;

            default:
                useDelegate = false;
        }
    }

    private void initForLong( long value ) {

        this.value = ( VALUE ) ( Long ) value;

        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqLong( name, ( value ) );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqLong( name, ( value ) );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltLong( name, ( value ) );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteLong( name, ( value ) );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtLong( name, ( value ) );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteLong( name, ( value ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inLongs( name, Conversions.larray( values ) );
                break;


            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenLong( name, ( value ),
                        Conversions.toLong( values[ 1 ] ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInLongs( name, Conversions.larray( values ) );

                break;

            default:
                useDelegate = false;
        }
    }

    private void initForByte( byte value ) {

        this.value = ( VALUE ) ( Byte ) value;

        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqByte( name, ( value ) );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqByte( name, ( value ) );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltByte( name, ( value ) );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteByte( name, ( value ) );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtByte( name, ( value ) );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteByte( name, ( value ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inBytes( name, Conversions.barray( values ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInBytes( name, Conversions.barray( values ) );

                break;


            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenByte( name, ( value ),
                        Conversions.toByte( values[ 1 ] ) );
                break;


            default:
                useDelegate = false;
        }
    }

    private void initForDate() {
        value = ( VALUE ) Conversions.toDate( value );

        if ( operator == Operator.BETWEEN ) {
            values[ 0 ] = ( VALUE ) Conversions.toDate( values[ 0 ] );

            values[ 1 ] = ( VALUE ) Conversions.toDate( values[ 1 ] );

        }

    }

    private void initForInt( int v ) {
        this.value = ( VALUE ) ( Integer ) v;


        switch ( operator ) {
            case EQUAL:
                nativeDelegate = CriteriaFactory.eqInt( name, v );
                break;

            case NOT_EQUAL:
                nativeDelegate = CriteriaFactory.notEqInt( name, v );
                break;

            case LESS_THAN:
                nativeDelegate = CriteriaFactory.ltInt( name, v );
                break;

            case LESS_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.lteInt( name, v );
                break;

            case GREATER_THAN:
                nativeDelegate = CriteriaFactory.gtInt( name, v );
                break;

            case GREATER_THAN_EQUAL:
                nativeDelegate = CriteriaFactory.gteInt( name, v );
                break;

            case BETWEEN:
                nativeDelegate = CriteriaFactory.betweenInt( name, v,
                        Conversions.toInt( values[ 1 ] ) );
                break;

            case IN:
                nativeDelegate = CriteriaFactory.inInts( name, Conversions.iarray( values ) );
                break;


            case NOT_IN:
                nativeDelegate = CriteriaFactory.notInInts( name, Conversions.iarray( values ) );

                break;

            default:
                useDelegate = false;
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy