MethodInfo mi = cf.addMethod(compareMethod);
mi.markSynthetic();
builder = new CodeBuilder(mi);
Label endLabel = builder.createLabel();
LocalVariable obj1 = builder.getParameter(0);
LocalVariable obj2 = builder.getParameter(1);
// The first rule always applies to the beans directly. All others
// apply to properties.
BeanComparator[] ruleParts = rules.getRuleParts();
BeanComparator bc = ruleParts[0];
if ((bc.mFlags & 0x01) != 0) {
// Reverse beans.
LocalVariable temp = obj1;
obj1 = obj2;
obj2 = temp;
}
// Handle the case when obj1 and obj2 are the same (or both null)
builder.loadLocal(obj1);
builder.loadLocal(obj2);
builder.ifEqualBranch(endLabel, true);
// Do null order checks for beans.
boolean nullHigh = (bc.mFlags & 0x02) == 0;
Label label = builder.createLabel();
builder.loadLocal(obj1);
builder.ifNullBranch(label, false);
builder.loadConstant(nullHigh ? 1 : -1);
builder.returnValue(TypeDesc.INT);
label.setLocation();
label = builder.createLabel();
builder.loadLocal(obj2);
builder.ifNullBranch(label, false);
builder.loadConstant(nullHigh ? -1 : 1);
builder.returnValue(TypeDesc.INT);
label.setLocation();
// Call 'using' Comparator if one is provided.
LocalVariable result =
builder.createLocalVariable("result", TypeDesc.INT);
if (bc.mUsingComparator != null) {
builder.loadThis();
builder.loadField("mUsingComparators", comparatorArrayType);
builder.loadConstant(0);
builder.loadFromArray(TypeDesc.forClass(Comparator.class));
builder.loadLocal(obj1);
builder.loadLocal(obj2);
builder.invoke(compareMethod);
builder.storeLocal(result);
builder.loadLocal(result);
label = builder.createLabel();
builder.ifZeroComparisonBranch(label, "==");
builder.loadLocal(result);
builder.returnValue(TypeDesc.INT);
label.setLocation();
}
// Cast bean parameters to correct types so that properties may be
// accessed.
TypeDesc type = TypeDesc.forClass(bc.mBeanClass);
builder.loadLocal(obj1);
builder.checkCast(type);
builder.storeLocal(obj1);
builder.loadLocal(obj2);
builder.checkCast(type);
builder.storeLocal(obj2);
// Generate code to perform comparisons against each property.
for (int i=1; i<ruleParts.length; i++) {
bc = ruleParts[i];
BeanProperty prop =
(BeanProperty)bc.getProperties().get(bc.mOrderByName);
Class propertyClass = prop.getType();
TypeDesc propertyType = TypeDesc.forClass(propertyClass);
// Create local variable to hold property values.
LocalVariable p1 = builder.createLocalVariable("p1", propertyType);
LocalVariable p2 = builder.createLocalVariable("p2", propertyType);
// Access properties and store in local variables.
builder.loadLocal(obj1);
builder.invoke(prop.getReadMethod());
builder.storeLocal(p1);
builder.loadLocal(obj2);
builder.invoke(prop.getReadMethod());
builder.storeLocal(p2);
if ((bc.mFlags & 0x01) != 0) {
// Reverse properties.
LocalVariable temp = p1;
p1 = p2;
p2 = temp;
}
Label nextLabel = builder.createLabel();