Package er.extensions.eof.qualifiers

Source Code of er.extensions.eof.qualifiers.ERXBetweenQualifier

//
//  ===========================================================================
//
//  Title:    ERXBetweenQualifier.java
//  Description:  [Description]
//  Author:    Petite Abeille
//  Creation Date:  Mon 20-Aug-2001
//  Legal:    Copyright (C) 2001 Petite Abeille. All Rights Reserved.
//      This class is hereby released for all uses.
//      No warranties whatsoever.
//  Motto:    "Victory belongs to those who believe in it the longest"
//
//  ---------------------------------------------------------------------------
//
package er.extensions.eof.qualifiers;

import java.math.BigDecimal;

import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOQualifierSQLGeneration;
import com.webobjects.eoaccess.EOSQLExpression;
import com.webobjects.eocontrol.EOClassDescription;
import com.webobjects.eocontrol.EOKeyValueArchiver;
import com.webobjects.eocontrol.EOKeyValueQualifier;
import com.webobjects.eocontrol.EOKeyValueUnarchiver;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.eocontrol.EOQualifierEvaluation;
import com.webobjects.eocontrol.EOQualifierVariable;
import com.webobjects.foundation.NSCoder;
import com.webobjects.foundation.NSComparator;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSMutableSet;
import com.webobjects.foundation.NSTimestamp;
import com.webobjects.foundation._NSStringUtilities;

import er.extensions.qualifiers.ERXKeyValueQualifier;

/**
* The between qualifier allows qualification on an
* attribute that is between two values. This qualifier
* supports both in-memory and sql based qualification.
*
* The SQL generated is of the form:
* "FOO BETWEEN 1 AND 3"
*
* Note this qualifier supports qualifing against String, Number
* and NSTimestamp values.
*/
public class ERXBetweenQualifier extends ERXKeyValueQualifier implements EOQualifierEvaluation, Cloneable
{
  /**
   * Do I need to update serialVersionUID?
   * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
   * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
   */
  private static final long serialVersionUID = 1L;

    /** register SQL generation support for the qualifier */
    static {
        EOQualifierSQLGeneration.Support.setSupportForClass(new BetweenQualifierSQLGenerationSupport(),
                                                            ERXBetweenQualifier.class);
    }


    //  ===========================================================================
    //  Constant(s)
    //  ---------------------------------------------------------------------------

    /** holds the between sql string */
    private static final String  BetweenStatement = " BETWEEN ";

    /** holds the and sql string */       
    private static final String  Separator = " AND ";

    //  ===========================================================================
    //  Class variable(s)
    //  ---------------------------------------------------------------------------

    //  ===========================================================================
    //  Instance variable(s)
    //  ---------------------------------------------------------------------------

    /** holds the key used to compare against */
    private String  _key = null;

    /** holds the minimun value */
    private Object  _minimumValue = null;

    /** holds the maximum value */
    private Object  _maximumValue = null;

    //  ===========================================================================
    //  Constructor method(s)
    //  ---------------------------------------------------------------------------

    /**
        * Creates a qualifier for a given key with a
        * min and max value specified.
        * @param aKey key to qualify against
        * @param aMinimumValue minimum value of the key
        * @param aMaximumValue maximum value of the key
        */
    public ERXBetweenQualifier(String aKey, Object aMinimumValue, Object aMaximumValue) {
        // Just to make EOKeyValueQualifier happy
        super(aKey, EOQualifier.QualifierOperatorEqual, aMinimumValue);
       
        setKey( aKey );
        setMinimumValue( aMinimumValue );
        setMaximumValue( aMaximumValue );
    }

    //  ===========================================================================
    //  Class method(s)
    //  ---------------------------------------------------------------------------

    //  ===========================================================================
    //  Instance method(s)
    //  ---------------------------------------------------------------------------

    /**
        * Gets the key to qualify against.
        * @return qualifier key
        */
    @Override
    public String key() {
        return _key;
    }

    /**
        * Sets the qualification key.
        * @param aValue for the qualification key.
        */
    public void setKey(String aValue) {
        _key = aValue;
    }

    /**
        * Gets the minimum value.
        * @return minimum value.
        */
    public Object minimumValue() {
        return _minimumValue;
    }

    /**
        * Sets the minimum value.
        * @param aValue new minimum value
        */
    public void setMinimumValue(Object aValue) {
        _minimumValue = aValue;
    }

    /**
        * Gets the maximum value.
        * @return maximum value.
        */
    public Object maximumValue() {
        return _maximumValue;
    }

    /**
        * Sets the maximum value.
        * @param aValue new maximum value
        */
    public void setMaximumValue(Object aValue) {
        _maximumValue = aValue;
    }

    //  ===========================================================================
    //  EOQualifier method(s)
    //  ---------------------------------------------------------------------------

    /**
        * Adds the qualification key of the qualifier to
        * the given set.
        * @param aSet to add the qualification key to.
        */
    @Override
    public void addQualifierKeysToSet(NSMutableSet aSet) {
        if ( aSet != null )
        {
            String  aKey = key();

            if ( aKey != null )
            {
                aSet.addObject( aKey );
            }
        }
    }

    /**
        * Creates another qualifier after replacing the values of the bindings.
        * Since this qualifier does not support qualifier binding keys a clone
        * of the qualifier is returned.
        * @param someBindings some bindings
        * @param requiresAll tells if the qualifier requires all bindings
        * @return clone of the current qualifier.
        */
    @Override
    public EOQualifier qualifierWithBindings(NSDictionary someBindings, boolean requiresAll) {
        return (EOQualifier) clone();
    }

    /**
        * This qualifier does not perform validation. This
        * is a no-op method.
        * @param aClassDescription to validation the qualifier keys
        *    against.
        */
    // FIXME: Should do something here...
    @Override
    public void validateKeysWithRootClassDescription(EOClassDescription aClassDescription) {
    }

    //  ===========================================================================
    //  EOQualifierSQLGeneration method(s)
    //  ---------------------------------------------------------------------------

    public static class BetweenQualifierSQLGenerationSupport extends EOQualifierSQLGeneration.Support {

        /**
        * Public constructor
         */
        public BetweenQualifierSQLGenerationSupport() {
            super();
        }

        /**
        * Constructs the BETWEEN sql string for sql qualification.
        * @param aSQLExpression to contruct the qualifier for.
        * @return BETWEEN sql string for the qualifier.
        */
        @Override
        public String sqlStringForSQLExpression(EOQualifier eoqualifier, EOSQLExpression aSQLExpression) {
            if ( ( aSQLExpression != null ) && ( aSQLExpression.entity() != null ) )
            {
                ERXBetweenQualifier betweenQualifier = (ERXBetweenQualifier)eoqualifier;
                EOEntity  anEntity = aSQLExpression.entity();
                String    aKey = betweenQualifier.key();
                Object    aMinimumValue = betweenQualifier.minimumValue();
                Object    aMaximumValue = betweenQualifier.maximumValue();

                if ( ( aKey != null ) && ( aMinimumValue != null ) && ( aMaximumValue != null ) )
                {
                    StringBuilder    aBuffer = new StringBuilder();
                    EOKeyValueQualifier  aMinimumQualifier = new EOKeyValueQualifier( aKey, EOQualifier.QualifierOperatorEqual, aMinimumValue );
                    EOKeyValueQualifier  aMaximumQualifier = new EOKeyValueQualifier( aKey, EOQualifier.QualifierOperatorEqual, aMaximumValue );

                    aMinimumQualifier = (EOKeyValueQualifier) anEntity.schemaBasedQualifier( aMinimumQualifier );
                    aMaximumQualifier = (EOKeyValueQualifier) anEntity.schemaBasedQualifier( aMaximumQualifier );

                    aBuffer.append( aSQLExpression.sqlStringForAttributeNamed( aMinimumQualifier.key() ) );

                    aBuffer.append( ERXBetweenQualifier.BetweenStatement );

                    aBuffer.append( aSQLExpression.sqlStringForValue( aMinimumQualifier.value(), aMinimumQualifier.key() ) );

                    aBuffer.append( ERXBetweenQualifier.Separator );

                    aBuffer.append( aSQLExpression.sqlStringForValue( aMaximumQualifier.value(), aMaximumQualifier.key() ) );

                    return aBuffer.toString();
                }
            }

            return null;
        }
       
        // ENHANCEME: This should support restrictive qualifiers on the root entity
        @Override
        public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier eoqualifier, EOEntity eoentity) {
            return (EOQualifier)eoqualifier.clone();
        }

        @Override
        public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier eoqualifier,
                                                                       EOEntity eoentity,
                                                                       String s) {
            // the key migration is the same as for EOKeyValueQualifier
            ERXBetweenQualifier betweenQualifier=(ERXBetweenQualifier)eoqualifier;
            return new ERXBetweenQualifier(_translateKeyAcrossRelationshipPath(betweenQualifier.key(), s, eoentity),
                                           betweenQualifier.minimumValue(),
                                           betweenQualifier.maximumValue());
        }
    }
   
    //  ===========================================================================
    //  EOQualifierEvaluation method(s)
    //  ---------------------------------------------------------------------------

    /**
        * Determines the comparator to use for a given object based
        * on the object's class.
        * @param anObject to find the comparator for
        * @return comparator to use when comparing objects of a given
        *     class.
        */
    // ENHANCEME: Should have a way to extend this.
    protected NSComparator comparatorForObject(Object anObject) {
        if ( anObject != null ) {
            Class    anObjectClass = anObject.getClass();
            Class[]    someClasses = { String.class, Number.class, NSTimestamp.class };
            NSComparator[]  someComparators = { NSComparator.AscendingStringComparator, NSComparator.AscendingNumberComparator, NSComparator.AscendingTimestampComparator };
            int    count = someClasses.length;

            for ( int index = 0; index < count; index++ ) {
                Class  aClass = someClasses[ index ];

                if ( aClass.isAssignableFrom( anObjectClass ) ) {
                    return someComparators[ index ];
                }
            }
        }

        return null;
    }

    /**
        * Compares an object to determine if it is within the
        * between qualification of the current qualifier. This
        * method is only used for in-memory qualification.
        * @return if the given object is within the boundries of
        *         the qualifier.
        */
    @Override
    public boolean evaluateWithObject(Object anObject) {
        if ( ( anObject != null ) && ( anObject instanceof NSKeyValueCoding ) ) {
            String  aKey = key();
            Object  aMinimumValue = minimumValue();
            Object  aMaximumValue = maximumValue();

            if ( ( aKey != null ) && ( aMinimumValue != null ) && ( aMaximumValue != null ) ) {
                Object  aValue = ( (NSKeyValueCoding) anObject ).valueForKey( aKey );

                if ( aValue != null ) {
                    NSComparator  aComparator = comparatorForObject( aValue );

                    if ( aComparator != null ) {
                        boolean  containsObject = false;

                        try {
                            int  anOrder = aComparator.compare( aMinimumValue, aValue );

                            if ( ( anOrder == NSComparator.OrderedSame ) || ( anOrder == NSComparator.OrderedAscending ) )
                            {
                                anOrder = aComparator.compare( aMaximumValue, aValue );

                                if ( ( anOrder == NSComparator.OrderedSame ) || ( anOrder == NSComparator.OrderedDescending ) )
                                {
                                    containsObject = true;
                                }
                            }
                        } catch(NSComparator.ComparisonException anException) {
                        }

                        return containsObject;
                    }
                }
            }
        }

        return false;
    }

    //  ===========================================================================
    //  Cloneable method(s)
    //  ---------------------------------------------------------------------------

    /**
        * Implementation of the Clonable interface.
        * @return clone of the qualifier
        */
    @Override
    public Object clone() {
        return new ERXBetweenQualifier(key(), minimumValue(), maximumValue());
    }

    @Override
    public String toString() {
        return "(" + _key + " between " + valueStringForValue(_minimumValue) + " and " + valueStringForValue(_maximumValue) + ")";
    }

    private String valueStringForValue(Object aValue) {
        String valueString;
        if(aValue == NSKeyValueCoding.NullValue)
            valueString = "null";
        else
        if(aValue instanceof String)
            valueString = "'" + (String)aValue + "'";
        else
        if((aValue instanceof Number) && !(aValue instanceof BigDecimal))
            valueString = aValue.toString();
        else
        if(aValue instanceof EOQualifierVariable)
            valueString = "$" + ((EOQualifierVariable)aValue).key();
        else
            valueString = "(" + (aValue == null ? "null" : aValue.getClass().getName()) + ")" + _NSStringUtilities.quotedStringWithQuote(aValue == null ? "null" : aValue.toString(), '\'');
        return  valueString;
    }

    @Override
    public Class classForCoder() {
      return getClass();
    }
   
  public static Object decodeObject(NSCoder coder) {
    String key = (String)coder.decodeObject();
    Object minimumValue = coder.decodeObject();
    Object maximumValue = coder.decodeObject();
    return new ERXBetweenQualifier(key, minimumValue, maximumValue);
  }

  @Override
  public void encodeWithCoder(NSCoder coder) {
    coder.encodeObject(key());
    coder.encodeObject(minimumValue());
    coder.encodeObject(maximumValue());
  }

  @Override
  public void encodeWithKeyValueArchiver(EOKeyValueArchiver archiver) {
    archiver.encodeObject(key(), "key");
    archiver.encodeObject(minimumValue(), "minimumValue");
    archiver.encodeObject(maximumValue(), "maximumValue");
  }

  public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver unarchiver) {
    return new ERXBetweenQualifier(
        (String)unarchiver.decodeObjectForKey("key"),
        unarchiver.decodeObjectForKey("minimumValue"),
        unarchiver.decodeObjectForKey("maximumValue"));
  }
 
}
TOP

Related Classes of er.extensions.eof.qualifiers.ERXBetweenQualifier

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.