Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to generate equals and compareTo methods for classes generated with jaxb

Tags:

java

jaxb

equals

Is it possible to generate equals and compareTo methods for classes generated with jaxb, I use jaxb to generate classes from a schema. These classes actually have guids that allow them to be uniquely identified but how can I implement an equals/compare method so that Collection classes such as Set would recognise duplicate instances of the same entity ?

like image 756
Paul Taylor Avatar asked Jan 13 '15 10:01

Paul Taylor


1 Answers

Disclaimer: I am the author of jaxb2-basics which provides JAXB2 plugins capable of generating hashCode and equals methods.

Here's usage example for Maven:

        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <extension>true</extension>
                <args>
                    <arg>-Xequals</arg>
                    <arg>-XhashCode</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>...</version>
                    </plugin>
                </plugins>
            </configuration>
        </plugin>

(See the documentation for Ant.)

You can use -XsimpleHashCode and -XsimpleEquals which generate runtime-less hashCode and equals methods (hash code or equals calculation is inlined) or -XhashCode/-Xequals which generate "strategic" hashCode and equals methods (hash code/equals calculations are delegated to the passed strategy methods).

Here's what -XsimpleHashCode generates:

public class Customer {

    ...

    public int hashCode() {
        int currentHashCode = 1;
        {
            currentHashCode = (currentHashCode* 31);
            String theAddress;
            theAddress = this.getAddress();
            if (theAddress!= null) {
                currentHashCode += theAddress.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            Boolean theBlueEyes;
            theBlueEyes = this.isBlueEyes();
            if (theBlueEyes!= null) {
                currentHashCode += theBlueEyes.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            String theFamilyName;
            theFamilyName = this.getFamilyName();
            if (theFamilyName!= null) {
                currentHashCode += theFamilyName.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            String theGivenName;
            theGivenName = this.getGivenName();
            if (theGivenName!= null) {
                currentHashCode += theGivenName.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            List<String> theMiddleInitials;
            theMiddleInitials = (this.isSetMiddleInitials()?this.getMiddleInitials():null);
            if (theMiddleInitials!= null) {
                currentHashCode += theMiddleInitials.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            String thePostCode;
            thePostCode = this.getPostCode();
            if (thePostCode!= null) {
                currentHashCode += thePostCode.hashCode();
            }
        }
        {
            currentHashCode = (currentHashCode* 31);
            boolean theSingle;
            theSingle = this.isSingle();
            currentHashCode += (theSingle? 1231 : 1237);
        }
        return currentHashCode;
    }

}

Here's what -XhashCode generates:

public class Customer implements HashCode
{

    ...

    public int hashCode(ObjectLocator locator, HashCodeStrategy strategy) {
        int currentHashCode = 1;
        {
            String theAddress;
            theAddress = this.getAddress();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "address", theAddress), currentHashCode, theAddress);
        }
        {
            Boolean theBlueEyes;
            theBlueEyes = this.isBlueEyes();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "blueEyes", theBlueEyes), currentHashCode, theBlueEyes);
        }
        {
            String theFamilyName;
            theFamilyName = this.getFamilyName();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "familyName", theFamilyName), currentHashCode, theFamilyName);
        }
        {
            String theGivenName;
            theGivenName = this.getGivenName();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "givenName", theGivenName), currentHashCode, theGivenName);
        }
        {
            List<String> theMiddleInitials;
            theMiddleInitials = (this.isSetMiddleInitials()?this.getMiddleInitials():null);
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "middleInitials", theMiddleInitials), currentHashCode, theMiddleInitials);
        }
        {
            String thePostCode;
            thePostCode = this.getPostCode();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "postCode", thePostCode), currentHashCode, thePostCode);
        }
        {
            boolean theSingle;
            theSingle = this.isSingle();
            currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "single", theSingle), currentHashCode, theSingle);
        }
        return currentHashCode;
    }

    public int hashCode() {
        final HashCodeStrategy strategy = JAXBHashCodeStrategy.INSTANCE;
        return this.hashCode(null, strategy);
    }

}

From my PoV, "strategic" versions are more powerful. Classes implement HashCode or Equals interfaces which accept locators and hash code/equals strategies. This allows you to control the hash code calculation or comparison from the outside. I often use this in unit tests not just to check if two objects equals or not, but also to find out where do they differ, exactly.

Both plugins generate reflection-free methods (this is critical for the performance). They also consider JAXB special cases like JAXBElements, primitive arrays and so on.

like image 112
lexicore Avatar answered Nov 08 '22 10:11

lexicore