//
// ERXInQualifier.java
// Project EOInQualifier
//
// Created by max on Mon Jul 15 2002
//
package er.extensions.eof;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOQualifierSQLGeneration;
import com.webobjects.eoaccess.EOSQLExpression;
import com.webobjects.eoaccess.EOUtilities;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.eocontrol.EOKeyValueQualifier;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
/**
* The ERXModuloQualifier is useful for creating qualifiers that
* will generate SQL using the 'mod' key word.<br>
* <br>
* For example constructing this qualifer:<br>
* <code>ERXModuloQualifier q = new ERXModuloQualifier("userId", 3, 5);</code>
* Then this qualifier would generate SQL of the form:
* ... where mod(userId,5)=3;
* Note that this syntax is Oracle specific
*/
// ENHANCEME: Should support restrictive qualifiers, don't need to subclass KeyValueQualifier
public class ERXModuloQualifier extends EOKeyValueQualifier implements 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 ModuloQualifierSQLGenerationSupport(), ERXModuloQualifier.class);
}
private int _modulo;
private int _index;
public int modulo() { return _modulo; }
public int index() { return _index; }
public ERXModuloQualifier(String key, int modulo, int index) {
super(key, EOQualifier.QualifierOperatorEqual, null);
_modulo=modulo;
_index=index;
}
/**
* String representation of the in
* qualifier.
* @return string description of the qualifier
*/
@Override
public String toString() {
return " <" + getClass().getName() + " key: " + key() + " > == "+index()+" mod "+modulo();
}
/** Tests if the given object's key is in the supplied values */
// FIXME: this doesn't work right with EOs when the key() is keypath across a relationship
@Override
public boolean evaluateWithObject(Object object) {
Object value = null;
if(object instanceof EOEnterpriseObject) {
EOEnterpriseObject eo = (EOEnterpriseObject)object;
EOEditingContext ec = eo.editingContext();
if(eo.classDescription().attributeKeys().containsObject(key())) {
value = NSKeyValueCodingAdditions.Utility.valueForKeyPath(eo, key());
} else if(EOUtilities.entityNamed(ec, eo.entityName()).primaryKeyAttributeNames().containsObject(key())) {
// when object is an EO and key() is a cross-relationship keypath, we drop through to this case
// and we'll fail.
value = EOUtilities.primaryKeyForObject(ec,eo).objectForKey(key());
}
} else {
value = NSKeyValueCodingAdditions.Utility.valueForKeyPath(object, key());
}
return value != null && (((Number)value).intValue() & modulo()) == index();
}
/*
* EOF seems to be wanting to clone qualifiers when
* they are inside an and-or qualifier without this
* method, ERXInQualifier is cloned into
* an EOKeyValueQualifier and the generated SQL is incorrect..
* @return cloned primary key list qualifier.
*/
@Override
public Object clone() {
return new ERXModuloQualifier(key(), modulo(), index());
}
/**
* Adds SQL generation support. Note that the database needs to support
* the MOD operator.
*/
public static class ModuloQualifierSQLGenerationSupport extends EOQualifierSQLGeneration.Support {
/**
* Public constructor
*/
public ModuloQualifierSQLGenerationSupport() {
super();
}
/**
* Generates the SQL string for an ERXInQualifier.
* @param eoqualifier an in qualifier
* @param e current eo sql expression
* @return SQL for the current qualifier.
*/
@Override
public String sqlStringForSQLExpression(EOQualifier eoqualifier, EOSQLExpression e) {
ERXModuloQualifier modQualifier = (ERXModuloQualifier)eoqualifier;
StringBuilder sb = new StringBuilder();
sb.append("mod(");
sb.append(e.sqlStringForAttributeNamed(modQualifier.key()));
sb.append(", ");
sb.append(modQualifier.modulo());
sb.append(")=");
sb.append(modQualifier.index());
return sb.toString();
}
// 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
ERXModuloQualifier modQualifier=(ERXModuloQualifier)eoqualifier;
return new ERXModuloQualifier(_translateKeyAcrossRelationshipPath(modQualifier.key(), s, eoentity),
modQualifier.modulo(), modQualifier.index());
}
}
}