package er.extensions.qualifiers;
import com.webobjects.eocontrol.EOAndQualifier;
import com.webobjects.eocontrol.EOKeyComparisonQualifier;
import com.webobjects.eocontrol.EOKeyValueQualifier;
import com.webobjects.eocontrol.EONotQualifier;
import com.webobjects.eocontrol.EOOrQualifier;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.eocontrol.EOQualifierEvaluation;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSRange;
import er.extensions.eof.ERXKey;
import er.extensions.eof.qualifiers.ERXExistsQualifier;
/**
* Takes a qualifier, traverses every subqualifier, and prepends every keypath
* with an extra keypath. This should be end up being similar to
* EOQualifierSQLGeneration.Support.qualifierMigratedFromEntityRelationshipPath
* except that it does not deal in entities.
*
* @author mschrag
*/
public class ERXPrefixQualifierTraversal extends ERXQualifierTraversal {
private String _prefix;
private NSMutableArray<EOQualifier> _qualifiers;
protected ERXPrefixQualifierTraversal(ERXKey prefix) {
_prefix = prefix.key() + ".";
}
/**
* Returns a qualifier with the given key prepended to every qualifier's
* key.
*
* @param qualifier
* the qualifier to prepend with a key
* @param prefix
* the key to prepend
* @return a new matching qualifier with the prefix prepended
*/
public static synchronized EOQualifier prefixQualifierWithKey(EOQualifierEvaluation qualifier, ERXKey prefix) {
ERXPrefixQualifierTraversal prefixTraversal = new ERXPrefixQualifierTraversal(prefix);
prefixTraversal.traverse(qualifier, true);
EOQualifier prefixedQualifier = prefixTraversal._qualifiers.lastObject();
return prefixedQualifier;
}
@Override
protected boolean traverseUnknownQualifier(EOQualifierEvaluation q) {
throw new UnsupportedOperationException("Unknown qualifier type '" + q.getClass().getName() + "'.");
}
@Override
protected boolean traverseNotQualifier(EONotQualifier q) {
ERXNotQualifier nq = new ERXNotQualifier(_qualifiers.lastObject());
_qualifiers.removeLastObject();
_qualifiers.addObject(nq);
return true;
}
@Override
protected boolean traverseOrQualifier(EOOrQualifier q) {
if (q.qualifiers().isEmpty()) {
_qualifiers.addObject(new ERXOrQualifier());
} else {
NSRange range = new NSRange(_qualifiers.count() - q.qualifiers().count(), q.qualifiers().count());
ERXOrQualifier oq = new ERXOrQualifier(_qualifiers.subarrayWithRange(range));
_qualifiers.removeObjectsInRange(range);
_qualifiers.addObject(oq);
}
return true;
}
@Override
protected boolean traverseAndQualifier(EOAndQualifier q) {
if (q.qualifiers().isEmpty()) {
_qualifiers.addObject(new ERXAndQualifier());
} else {
NSRange range = new NSRange(_qualifiers.count() - q.qualifiers().count(), q.qualifiers().count());
ERXAndQualifier aq = new ERXAndQualifier(_qualifiers.subarrayWithRange(range));
_qualifiers.removeObjectsInRange(range);
_qualifiers.addObject(aq);
}
return true;
}
@Override
protected boolean traverseKeyValueQualifier(EOKeyValueQualifier q) {
ERXKeyValueQualifier kvq = new ERXKeyValueQualifier(_prefix + q.key(), q.selector(), q.value());
_qualifiers.addObject(kvq);
return true;
}
@Override
protected boolean traverseKeyComparisonQualifier(EOKeyComparisonQualifier q) {
ERXKeyComparisonQualifier kcq = new ERXKeyComparisonQualifier(_prefix + q.leftKey(), q.selector(), _prefix + q.rightKey());
_qualifiers.addObject(kcq);
return true;
}
@Override
protected boolean traverseFalseQualifier(ERXFalseQualifier q) {
_qualifiers.addObject(q);
return true;
}
@Override
protected boolean traverseTrueQualifier(ERXTrueQualifier q) {
_qualifiers.addObject(q);
return true;
}
@Override
protected boolean traverseExistsQualifier(ERXExistsQualifier q) {
String newBaseKeyPath = q.baseKeyPath() != null ? _prefix + q.baseKeyPath() : _prefix.substring(0, _prefix.length() - 1);
_qualifiers.add(new ERXExistsQualifier(q.subqualifier(), newBaseKeyPath, q.usesInQualInstead()));
return true;
}
@Override
public synchronized void traverse(EOQualifierEvaluation q, boolean postOrder) {
if (!postOrder) {
throw new IllegalArgumentException("ERXPrefixQualifierTraversal requires a postOrder traversal.");
}
_qualifiers = new NSMutableArray<>();
super.traverse(q, postOrder);
}
}