package com.webobjects.eoaccess;
import com.webobjects.foundation.NSArray;
/**
* EOAdaptorOpComparator that handles vertical inheritance.
*
*/
public class ERXAdaptorOpComparator extends EOAdaptorOpComparator {
/**
* @param entityNameOrdering ordering of entity names to base sorting on
*/
public ERXAdaptorOpComparator(NSArray entityNameOrdering) {
super(entityNameOrdering);
}
@Override
public int compare(Object object1, Object object2)
throws com.webobjects.foundation.NSComparator.ComparisonException {
if(object1 == null ||
object2 == null ||
!(object1 instanceof EOAdaptorOperation) ||
!(object2 instanceof EOAdaptorOperation)) {
throw new com.webobjects.foundation.NSComparator.ComparisonException("Unable to compare objects. Objects should be instance of class EOAdaptorOperation. Comparison was made with " + object1 + " and " + object2 + ".");
}
EOAdaptorOperation a = (EOAdaptorOperation)object1;
EOAdaptorOperation b = (EOAdaptorOperation)object2;
int aOpType = a.adaptorOperator();
int bOpType = b.adaptorOperator();
if(aOpType == 4) {
aOpType = decodeAdaptorTypeForEntityAndStoredProcedure(a.entity(), a.storedProcedure());
}
if(bOpType == 4) {
bOpType = decodeAdaptorTypeForEntityAndStoredProcedure(b.entity(), b.storedProcedure());
}
if(aOpType != bOpType) {
return aOpType >= bOpType ? 1 : -1;
}
NSArray entityNames = _context;
String entityNameA = a.entity().name();
String entityNameB = b.entity().name();
// Use correct name for flattened attributes
if (entityNameA.equals(entityNameB) && a.entity().parentEntity() != null) {
entityNameA = entityNameFromAdaptorOperation(a);
entityNameB = entityNameFromAdaptorOperation(b);
}
int aPriority = entityNames == null ? 0 : entityNames.indexOfObject(entityNameA);
int bPriority = entityNames == null ? 0 : entityNames.indexOfObject(entityNameB);
int order = 1;
if(aPriority == bPriority) {
order = 0;
}
else if(aPriority < bPriority) {
order = -1;
}
return (aOpType == 3) ? -order : order;
}
/**
* Returns the name of EOEntity updated by adaptorOp. If this is updating through a flattened
* attribute, the name returned is the Entity of the target attribute.
*
* @param adaptorOp EOAdaptorOperation to return Entity name from
* @return name of EOEntity updated by adaptorOp
*/
protected String entityNameFromAdaptorOperation(EOAdaptorOperation adaptorOp) {
EOEntity entity = adaptorOp.entity();
// If there are no changed valued (e.g. EOAdaptorDeleteOperator), use the standard entity
if (adaptorOp.changedValues() == null)
{
return entity.name();
}
// Flattened attributes are grouped together by entity so any attribute in changedValues should work
NSArray<String> attrNames = adaptorOp.changedValues().allKeys();
for(int i = 0; i < attrNames.count(); i++) {
EOAttribute attribute = entity.attributeNamed(attrNames.objectAtIndex(i));
/*
* Sometimes attributes are named like "NeededByEOF0" for vertical inheritance.
* With single table inheritance, attributes names from other entities may appear.
* Better safe than sorry :) Keep checking until we find an attribute on the
* entity for the given attribute name.
*
* Long discussion about this here:
* http://article.gmane.org/gmane.comp.web.webobjects.wonder-disc/8055
*
* I think this should do the trick and make vertical and single table happy :)
*/
if(attribute != null) {
if(!attribute.isFlattened()) {
return entity.name();
}
return attribute.targetAttribute().entity().name();
}
}
return entity.name();
}
private int decodeAdaptorTypeForEntityAndStoredProcedure(EOEntity entity, EOStoredProcedure sp)
{
if(entity.storedProcedureForOperation("EOInsertProcedure") == sp)
{
return 1;
}
return entity.storedProcedureForOperation("EODeleteProcedure") != sp ? 4 : 3;
}
}