package org.opentrafficsim.road; import static org.junit.Assert.fail; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collection; import org.junit.Test; /** * Verify that all classes have a toString method (unless the class in non-instantiable, or an enum, or abstract.
* Verify that no class overrides equals without overriding hashCode.
* Verify that classes that can be instantiated are Serializable for those classes that this makes sense. *

* Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License. *

* @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016
* @author Alexander Verbraeck * @author Peter Knoppers * @author Wouter Schakel */ public class VerifyRequiredMethods { /** * Check that all classes have a toString method. */ @Test public final void toStringTest() { Collection> classList = ClassList.classList("org.opentrafficsim", true); for (Class c : classList) { if (Exception.class.isAssignableFrom(c)) { continue; } if (ClassList.isAnonymousInnerClass(c)) { continue; } Method toStringMethod = null; boolean isAbstract = false; for (String modifierString : Modifier.toString(c.getModifiers()).split(" ")) { if (modifierString.equals("abstract")) { isAbstract = true; break; } } for (Method m : c.getDeclaredMethods()) { if (m.getName().equals("toString") && m.getParameterCount() == 0) { toStringMethod = m; } } if (null == toStringMethod) { // Get the nearest toString method from the parent tree try { toStringMethod = c.getMethod("toString"); } catch (NoSuchMethodException | SecurityException exception) { exception.printStackTrace(); fail("Cannot happen: getMethod(\"toString\") should never fail - there is one in Object"); } boolean isFinal = false; for (String modifierString : Modifier.toString(toStringMethod.getModifiers()).split(" ")) { if ("final".equals(modifierString)) { isFinal = true; break; } } if (isFinal) { System.out.println("Class " + c.getName() + " can not override the toString method because a super " + "class implements a final toString method"); } else if (!ClassList.hasNonStaticFields(c)) { System.out.println("Class " + c.getName() + " does not have to override the toString method because it does not have non-static fields"); } else if (isAbstract) { System.out.println("Class " + c.getName() + " does not have to override the toString method because " + "it is an abstract class"); } else if (c.isEnum()) { System.out.println("Class " + c.getName() + " does not have to override toString because this class " + "is an enum"); } else { // fail("Class " + c.getName() + " does not (but should) override toString"); System.err.println("Class " + c.getName() + " does not (but should) override toString"); } } } } /** * Check that all classes implement the Serializable interface. */ @Test public final void serializableTest() { Collection> classList = ClassList.classList("org.opentrafficsim", true); for (Class c : classList) { // if (c.getName().endsWith("AccelerationContourPlot")) // { // System.out.println("Let op"); // } if (Serializable.class.isAssignableFrom(c)) { if (c.isEnum()) { // System.out.println("Class " + c.getName() + " is an enum and (by inheritance) implements Serializable"); } else if (!ClassList.hasNonStaticFields(c)) { System.err.println("Class " + c.getName() + " does not contain non-static fields and should NOT implement Serializable"); } else if (Thread.class.isAssignableFrom(c)) { System.err.println("Class " + c.getName() + " is a thread and should NOT implement Serializable"); } else if (ClassList.isAnonymousInnerClass(c)) { System.err.println("Class " + c.getName() + " is an anonymous inner class and should NOT implement Serializable"); } else if (Exception.class.isAssignableFrom(c)) { System.out.println("Class " + c.getName() + " is an Exception and (correctly) implements Serializable"); } else { // System.out.println("Class " + c.getName() + " should (and does) implement Serializable"); } } else { if (c.isEnum()) { System.err.println("Class " + c.getName() + " is an enum and should (by inheritence) implement Serializable"); } else if (!ClassList.hasNonStaticFields(c)) { // System.out.println("Class " + c.getName() // + " does not contain non-static fields and (correctly does not implement Serializable"); } else if (Thread.class.isAssignableFrom(c)) { // System.out.println("Class " + c.getName() + // " is a thread and (correctly) does not implement Serializable"); } else if (ClassList.isAnonymousInnerClass(c)) { // System.out.println("Class " + c.getName() // + " is an anonymous inner class and (correctly) does not implement Serializable"); } else if (Exception.class.isAssignableFrom(c)) { System.err.println("Class " + c.getName() + " is an Exception and should (but does NOT) implement Serializable"); } else { System.err.println("Class " + c.getName() + " should (but does NOT) implement Serializable"); } } } } /** * Check that all classes that implement equals also implement hashCode. */ @Test public final void equalsAndHashCodeTest() { Collection> classList = ClassList.classList("org.opentrafficsim", true); for (Class c : classList) { if (Exception.class.isAssignableFrom(c)) { continue; } Method equalsMethod = null; Method hashCodeMethod = null; for (Method m : c.getDeclaredMethods()) { if (m.getName().equals("equals")) { equalsMethod = m; } else if (m.getName().equals("hashCode")) { hashCodeMethod = m; } } if (null == equalsMethod) { if (null == hashCodeMethod) { // System.out.println("Class " + c.getName() + " implements neither equals nor hashCode"); } else { // System.out.println("Class " + c.getName() + " implements hashCode, but not equals"); } } else if (null == hashCodeMethod) { fail("Class " + c.getName() + " implements equals but NOT hashCode"); } else { // System.out.println("Class " + c.getName() + " implements equals and hashCode (good)"); } } } }