Closed rviado closed 6 years ago
Interesting idea, but JAXB2 Basics provide "normal" equals
and hashCode
plugins which cover your use case.
These plugins generate equals
and hashCode
methods which accept locators (irrelevant here) as well as a strategy. The strategy implements comparison (or hash code generation). There are default strategies but you can also provide your own.
This allows you to implement and supply the desired comparison or hash code generation strategy in the runtime. For instance if you want to use isEqual
for ZonedDateTime
, you can capture this in your custom equality strategy. You can also configure equals
or hashCode
plugins to use your strategy class by default.
This is the kind of code you get generated:
public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy2 strategy) {
if ((object == null)||(this.getClass()!= object.getClass())) {
return false;
}
if (this == object) {
return true;
}
final IssueGH26Type that = ((IssueGH26Type) object);
{
String lhsA;
lhsA = this.getA();
String rhsA;
rhsA = that.getA();
if (!strategy.equals(LocatorUtils.property(thisLocator, "a", lhsA), LocatorUtils.property(thatLocator, "a", rhsA), lhsA, rhsA, this.isSetA(), that.isSetA())) {
return false;
}
}
{
List<Serializable> lhsBOrC;
lhsBOrC = (this.isSetBOrC()?this.getBOrC():null);
List<Serializable> rhsBOrC;
rhsBOrC = (that.isSetBOrC()?that.getBOrC():null);
if (!strategy.equals(LocatorUtils.property(thisLocator, "bOrC", lhsBOrC), LocatorUtils.property(thatLocator, "bOrC", rhsBOrC), lhsBOrC, rhsBOrC, this.isSetBOrC(), that.isSetBOrC())) {
return false;
}
}
{
List<JAXBElement<String>> lhsDOrE;
lhsDOrE = (this.isSetDOrE()?this.getDOrE():null);
List<JAXBElement<String>> rhsDOrE;
rhsDOrE = (that.isSetDOrE()?that.getDOrE():null);
if (!strategy.equals(LocatorUtils.property(thisLocator, "dOrE", lhsDOrE), LocatorUtils.property(thatLocator, "dOrE", rhsDOrE), lhsDOrE, rhsDOrE, this.isSetDOrE(), that.isSetDOrE())) {
return false;
}
}
{
String lhsZ;
lhsZ = this.getZ();
String rhsZ;
rhsZ = that.getZ();
if (!strategy.equals(LocatorUtils.property(thisLocator, "z", lhsZ), LocatorUtils.property(thatLocator, "z", rhsZ), lhsZ, rhsZ, this.isSetZ(), that.isSetZ())) {
return false;
}
}
return true;
}
public boolean equals(Object object) {
final EqualsStrategy2 strategy = new IssueJIIB42EqualsStrategy();
return equals(null, null, object, strategy);
}
You can see that this code does not contain actual comparison, it calles the provided strategy instance.
I stumbled upon a use case wherein I needed to use the "isEqual" instead of the "equals" method on ZonedDateTime objects.
I ended up enhancing the code to make simpleequals configurable by just adding a notSoSimpleEquals.properties file in META-INF/jaxb2/plugin folder.
This file is used to configure a strategy based on the object type.
Example:
java.time.ZonedDateTime=method:isEqual my.own.HelloWorld=adapter:my.special.EqualsAdapter
The first line above will instruct simpleequals plugin to use the method "isEqual" on object of type ZoneDateTime
The second line will instruct simpleequals plugin to use an adapter on HelloWorld objects. The adapter must implement a public "isEqual" static method that accepts two objects that will be compared for equality. The method must return a boolean value depending on the result of the comparison.
The enhancement is so simple and yet gives so much flexibility that it may be warranted to be included in the main distribution.
Code below (Change is isolated only to EqualsCodeGenerationImplementor.java in onObject method)
@Override public void onObject(EqualsArguments arguments, JBlock block, boolean isAlwaysSet) { String type = arguments.leftValue().type().fullName(); JInvocation condition = arguments.leftValue().invoke("equals").arg(arguments.rightValue());