/*==========================================================================*\
| $Id: QualifierAugmenter.java,v 1.1 2010/05/11 14:51:55 aallowat Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2006-2008 Virginia Tech
|
| This file is part of Web-CAT.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU Affero General Public License as published
| by the Free Software Foundation; either version 3 of the License, or
| (at your option) any later version.
|
| Web-CAT is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU Affero General Public License
| along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package org.webcat.core;
import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModelGroup;
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.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import er.extensions.eof.ERXQ;
import er.extensions.eof.qualifiers.ERXBetweenQualifier;
import er.extensions.eof.qualifiers.ERXInQualifier;
import er.extensions.qualifiers.ERXKeyComparisonQualifier;
import er.extensions.qualifiers.ERXKeyValueQualifier;
//-------------------------------------------------------------------------
/**
* Methods used to augment qualifiers in order to support the proper fetching
* of objects that have migratory attributes.
*
* @author Tony Allevato
* @version $Id: QualifierAugmenter.java,v 1.1 2010/05/11 14:51:55 aallowat Exp $
*/
public class QualifierAugmenter
{
// ----------------------------------------------------------
public QualifierAugmenter(String entityName, EOQualifier q)
{
this.entityName = entityName;
this.augmentedKeyPaths = new NSMutableArray<String>();
originalQualifier = q;
augmentedQualifier = augmentQualifier(q, this);
}
// ----------------------------------------------------------
public EOQualifier originalQualifier()
{
return originalQualifier;
}
// ----------------------------------------------------------
public EOQualifier augmentedQualifier()
{
return augmentedQualifier;
}
// ----------------------------------------------------------
public NSArray<String> augmentedKeyPaths()
{
return augmentedKeyPaths;
}
// ----------------------------------------------------------
public boolean isSignificantDifference()
{
return (augmentedKeyPaths.count() > 0);
}
// ----------------------------------------------------------
/**
* Deeply traverses a qualifier tree and returns a new qualifier where
* any comparisons involving migratory attributes have been augmented to
* the form
* <code>(original attribute comparison OR attribute == NULL)</code>.
*
* @param q the qualifier to augmented
* @return a new qualifier that has been augmented
*/
private static EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
if (q == null)
{
return null;
}
Class<?> qType = q.getClass();
IAugmenter auger = augmenters.objectForKey(qType);
if (auger != null)
{
return auger.augmentQualifier(q, augmenter);
}
else
{
return (EOQualifier) q.clone();
}
}
// ----------------------------------------------------------
private void addAugmentedKeyPath(String keypath)
{
augmentedKeyPaths.addObject(keypath);
}
// ----------------------------------------------------------
private boolean isKeypathMigratoryAttribute(String keypath)
{
EOEntity entity = EOModelGroup.defaultGroup().entityNamed(entityName);
if (entity == null)
return false;
EOAttribute attribute = entity._attributeForPath(keypath);
if (attribute == null || attribute.userInfo() == null)
return false;
String needsMigration = (String) attribute.userInfo().objectForKey(
"needsMigration");
return (needsMigration != null && Boolean.parseBoolean(needsMigration));
}
// ----------------------------------------------------------
/**
* The interface that defines the methods used to augment qualifiers.
*/
private interface IAugmenter
{
// ----------------------------------------------------------
EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter);
}
// ----------------------------------------------------------
private static class AndQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
EOAndQualifier aq = (EOAndQualifier) q;
NSMutableArray<EOQualifier> children =
new NSMutableArray<EOQualifier>();
for (EOQualifier child : aq.qualifiers())
{
children.addObject(QualifierAugmenter.augmentQualifier(
child, augmenter));
}
return new EOAndQualifier(children);
}
}
// ----------------------------------------------------------
private static class OrQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
EOOrQualifier oq = (EOOrQualifier) q;
NSMutableArray<EOQualifier> children =
new NSMutableArray<EOQualifier>();
for (EOQualifier child : oq.qualifiers())
{
children.addObject(QualifierAugmenter.augmentQualifier(
child, augmenter));
}
return new EOOrQualifier(children);
}
}
// ----------------------------------------------------------
private static class NotQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
EONotQualifier nq = (EONotQualifier) q;
return ERXQ.not(QualifierAugmenter.augmentQualifier(nq
.qualifier(), augmenter));
}
}
// ----------------------------------------------------------
private static class InQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
ERXInQualifier iq = (ERXInQualifier) q;
if (augmenter.isKeypathMigratoryAttribute(iq.key()))
{
augmenter.addAugmentedKeyPath(iq.key());
return ERXQ.or(
new ERXInQualifier(iq.key(), iq.values()),
ERXQ.isNull(iq.key()));
}
else
{
return (EOQualifier) iq.clone();
}
}
}
// ----------------------------------------------------------
private static class BetweenQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
ERXBetweenQualifier bq = (ERXBetweenQualifier) q;
if (augmenter.isKeypathMigratoryAttribute(bq.key()))
{
augmenter.addAugmentedKeyPath(bq.key());
return ERXQ.or(
new ERXBetweenQualifier(
bq.key(), bq.minimumValue(), bq.maximumValue()),
ERXQ.isNull(bq.key()));
}
else
{
return (EOQualifier) bq.clone();
}
}
}
// ----------------------------------------------------------
private static class KeyValueQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
EOKeyValueQualifier kvq = (EOKeyValueQualifier) q;
if (augmenter.isKeypathMigratoryAttribute(kvq.key()))
{
augmenter.addAugmentedKeyPath(kvq.key());
return ERXQ.or(
(EOQualifier) kvq.clone(),
ERXQ.isNull(kvq.key()));
}
else
{
return (EOQualifier) kvq.clone();
}
}
}
// ----------------------------------------------------------
private static class ERXKeyValueQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
ERXKeyValueQualifier kvq = (ERXKeyValueQualifier) q;
if (augmenter.isKeypathMigratoryAttribute(kvq.key()))
{
augmenter.addAugmentedKeyPath(kvq.key());
return ERXQ.or(
(EOQualifier) kvq.clone(),
ERXQ.isNull(kvq.key()));
}
else
{
return (EOQualifier) kvq.clone();
}
}
}
// ----------------------------------------------------------
private static class KeyComparisonQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
EOKeyComparisonQualifier kcq = (EOKeyComparisonQualifier) q;
NSMutableArray<EOQualifier> subq =
new NSMutableArray<EOQualifier>();
if (augmenter.isKeypathMigratoryAttribute(kcq.leftKey()))
{
augmenter.addAugmentedKeyPath(kcq.leftKey());
subq.addObject(ERXQ.isNull(kcq.leftKey()));
}
if (augmenter.isKeypathMigratoryAttribute(kcq.rightKey()))
{
augmenter.addAugmentedKeyPath(kcq.rightKey());
subq.addObject(ERXQ.isNull(kcq.rightKey()));
}
if (subq.count() > 0)
{
subq.insertObjectAtIndex((EOQualifier) kcq.clone(), 0);
return ERXQ.or((EOQualifier[]) subq.toArray());
}
else
{
return (EOQualifier) kcq.clone();
}
}
}
// ----------------------------------------------------------
private static class ERXKeyComparisonQualifierAugmenter
implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
ERXKeyComparisonQualifier kcq = (ERXKeyComparisonQualifier) q;
NSMutableArray<EOQualifier> subq =
new NSMutableArray<EOQualifier>();
if (augmenter.isKeypathMigratoryAttribute(kcq.leftKey()))
{
augmenter.addAugmentedKeyPath(kcq.leftKey());
subq.addObject(ERXQ.isNull(kcq.leftKey()));
}
if (augmenter.isKeypathMigratoryAttribute(kcq.rightKey()))
{
augmenter.addAugmentedKeyPath(kcq.rightKey());
subq.addObject(ERXQ.isNull(kcq.rightKey()));
}
if (subq.count() > 0)
{
subq.insertObjectAtIndex((EOQualifier) kcq.clone(), 0);
return ERXQ.or((EOQualifier[]) subq.toArray());
}
else
{
return (EOQualifier) kcq.clone();
}
}
}
// ----------------------------------------------------------
private static class SubqueryQualifierAugmenter implements IAugmenter
{
// ----------------------------------------------------------
public EOQualifier augmentQualifier(EOQualifier q,
QualifierAugmenter augmenter)
{
QualifierInSubquery qis = (QualifierInSubquery) q;
EOQualifier augq = QualifierAugmenter.augmentQualifier(
qis.qualifier(), augmenter);
if (qis.relationshipName() != null)
{
return new QualifierInSubquery(augq, qis.entityName(),
qis.relationshipName());
}
else
{
return new QualifierInSubquery(augq, qis.entityName(),
qis.attributeName(), qis.destinationAttributeName());
}
}
}
//~ Static/instance variables .............................................
private String entityName;
private EOQualifier originalQualifier;
private EOQualifier augmentedQualifier;
private NSMutableArray<String> augmentedKeyPaths;
/** A mapping between qualifier classes and converter instances. */
private static NSMutableDictionary<Class<?>, IAugmenter> augmenters;
static
{
augmenters = new NSMutableDictionary<Class<?>, IAugmenter>();
augmenters.setObjectForKey(new AndQualifierAugmenter(),
EOAndQualifier.class);
augmenters.setObjectForKey(new OrQualifierAugmenter(),
EOOrQualifier.class);
augmenters.setObjectForKey(new NotQualifierAugmenter(),
EONotQualifier.class);
augmenters.setObjectForKey(new InQualifierAugmenter(),
ERXInQualifier.class);
augmenters.setObjectForKey(new BetweenQualifierAugmenter(),
ERXBetweenQualifier.class);
augmenters.setObjectForKey(new KeyValueQualifierAugmenter(),
EOKeyValueQualifier.class);
augmenters.setObjectForKey(new ERXKeyValueQualifierAugmenter(),
ERXKeyValueQualifier.class);
augmenters.setObjectForKey(new KeyComparisonQualifierAugmenter(),
EOKeyComparisonQualifier.class);
augmenters.setObjectForKey(new ERXKeyComparisonQualifierAugmenter(),
ERXKeyComparisonQualifier.class);
augmenters.setObjectForKey(new SubqueryQualifierAugmenter(),
QualifierInSubquery.class);
}
}