/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file. */
package er.extensions.qualifiers;
import java.util.Enumeration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.EOQualifierEvaluation;
import er.extensions.eof.qualifiers.ERXExistsQualifier;
/**
* Traverse a network of qualifiers until a traversal method returns false.
* Subclass and implement the methods you need.
*/
public class ERXQualifierTraversal {
private static final Logger log = LoggerFactory.getLogger(ERXQualifierTraversal.class);
/**
* Catch-all visitor, will get called for each qualifier.
*
* @param q
* the qualifier to process
*/
protected void visit(EOQualifierEvaluation q) {
}
/**
* Should traverse unknown qualifier? Logs an error.
*
* @param q
* the qualifier to process
* @return should traverse boolean qualifier
*/
protected boolean traverseUnknownQualifier(EOQualifierEvaluation q) {
log.error("Found unknown qualifier type: {}", q.getClass().getName());
return true;
}
/**
* Should traverse not qualifier?
*
* @param q
* the qualifier to process
* @return should traverse not qualifier
*/
protected boolean traverseNotQualifier(EONotQualifier q) {
return true;
}
/**
* Should traverse or qualifier?
*
* @param q
* the qualifier to process
* @return should traverse or qualifier
*/
protected boolean traverseOrQualifier(EOOrQualifier q) {
return true;
}
/**
* Should traverse and qualifier?
*
* @param q
* the qualifier to process
* @return should traverse and qualifier
*/
protected boolean traverseAndQualifier(EOAndQualifier q) {
return true;
}
/**
* Should traverse a key value qualifier?
*
* @param q
* the qualifier to process
* @return should traverse key value qualifier
*/
protected boolean traverseKeyValueQualifier(EOKeyValueQualifier q) {
return true;
}
/**
* Should traverse key comparison qualifier?
*
* @param q
* the qualifier to process
* @return should traverse key comparison qualifier
*/
protected boolean traverseKeyComparisonQualifier(EOKeyComparisonQualifier q) {
return true;
}
/**
* Should traverse true qualifier?
*
* @param q
* the qualifier to process
* @return should traverse true qualifier
*/
protected boolean traverseTrueQualifier(ERXTrueQualifier q) {
return true;
}
/**
* Should traverse false qualifier?
*
* @param q
* the qualifier to process
* @return should traverse false qualifier
*/
protected boolean traverseFalseQualifier(ERXFalseQualifier q) {
return true;
}
/**
* Should traverse exists qualifier?
*
* @param q
* the qualifier to process
* @return should traverse exists qualifier
*/
protected boolean traverseExistsQualifier(ERXExistsQualifier q) {
return true;
}
/**
* Traverses the supplied qualifier
*
* @param q
* the qualifier to process
* @param postOrder
* if true, the qualifier is traversed from the bottom to the top
* @return whether or not to traverse the qualifier
*/
@SuppressWarnings("cast")
private boolean traverseQualifier(EOQualifierEvaluation q, boolean postOrder) {
Boolean result = null;
if (q == null)
result = Boolean.TRUE;
else {
visit(q);
if (q instanceof EOOrQualifier) {
EOOrQualifier aq = (EOOrQualifier) q;
if (!postOrder) {
result = traverseOrQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
if (result == null || result.booleanValue()) {
for (Enumeration e = aq.qualifiers().objectEnumerator(); e.hasMoreElements();) {
if (!traverseQualifier((EOQualifierEvaluation) e.nextElement(), postOrder)) {
result = Boolean.FALSE;
break;
}
}
}
if (postOrder && (result == null || result.booleanValue())) {
result = traverseOrQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
}
else if (q instanceof EOAndQualifier) {
EOAndQualifier aq = (EOAndQualifier) q;
if (!postOrder) {
result = traverseAndQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
if (result == null || result.booleanValue()) {
for (Enumeration e = aq.qualifiers().objectEnumerator(); e.hasMoreElements();) {
if (!traverseQualifier((EOQualifierEvaluation) e.nextElement(), postOrder)) {
result = Boolean.FALSE;
break;
}
}
}
if (postOrder && (result == null || result.booleanValue())) {
result = traverseAndQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
}
else if (q instanceof EONotQualifier) {
EONotQualifier aq = (EONotQualifier) q;
if (!postOrder) {
result = traverseNotQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
if (result == null || result.booleanValue()) {
result = traverseQualifier((EOQualifierEvaluation) aq.qualifier(), postOrder) ? Boolean.TRUE : Boolean.FALSE;
}
if (postOrder && (result == null || result.booleanValue())) {
result = traverseNotQualifier(aq) ? Boolean.TRUE : Boolean.FALSE;
}
}
else if (q instanceof EOKeyValueQualifier) {
result = traverseKeyValueQualifier((EOKeyValueQualifier) q) ? Boolean.TRUE : Boolean.FALSE;
}
else if (q instanceof EOKeyComparisonQualifier) {
result = traverseKeyComparisonQualifier((EOKeyComparisonQualifier) q) ? Boolean.TRUE : Boolean.FALSE;
}
else if (q instanceof ERXTrueQualifier) {
result = traverseTrueQualifier((ERXTrueQualifier) q) ? Boolean.TRUE : Boolean.FALSE;
}
else if (q instanceof ERXFalseQualifier) {
result = traverseFalseQualifier((ERXFalseQualifier) q) ? Boolean.TRUE : Boolean.FALSE;
}
else if (q instanceof ERXExistsQualifier) {
result = traverseExistsQualifier((ERXExistsQualifier) q) ? Boolean.TRUE : Boolean.FALSE;
}
else {
result = traverseUnknownQualifier(q) ? Boolean.TRUE : Boolean.FALSE;
}
if (result == null) {
throw new RuntimeException("Found unknown qualifier type:" + q.getClass().getName());
}
}
return result.booleanValue();
}
/**
* Visit every descendent qualifier in the given qualifier tree in a preorder traversal.
*
* @param q
* the root qualifier to traverse
*/
public void traverse(EOQualifierEvaluation q) {
traverseQualifier(q, false);
}
/**
* Visit every descendent qualifier in the given qualifier tree.
*
* @param q
* the root qualifier to traverse
* @param postOrder
* if true, the qualifier is traversed from the bottom to the top
*/
public void traverse(EOQualifierEvaluation q, boolean postOrder) {
traverseQualifier(q, postOrder);
}
}