/*
   * A helper for sanity checking de-/serialization.
   * We test two objects to be structurally equal by means of reflection.
   */
  public static boolean structurallyEqual(Object o1, Object o2) {
    try {
      if (o1.getClass().getName().equals(o2.getClass().getName())) {

        for (Class<?> obj = o1.getClass(); !obj.equals(Object.class); obj = obj.getSuperclass()) {
          Field[] f1 = obj.getDeclaredFields();
          Field[] f2 = obj.getDeclaredFields();

          for (int i = 0; i < f1.length; i++) {
            f1[i].setAccessible(true);
            f2[i].setAccessible(true);
            // check if fields are primitive types and compare
            if ((f1[i].getType().isPrimitive() && f2[i].getType().isPrimitive())) {
              if (!(f1[i].getName().equals(f2[i].getName()))) return false;
              else {
                if (!(f1[i].get(o1).equals(f2[i].get(o2)))) {
                  return false;
                }
              }
              // otherwise, they must be objects
            } else {
              // to be equal, both can not be null
              if (f1[i].get(o1) != null && f2[i].get(o2) != null) {
                // check, if they are of the same class
                if (f1[i].get(o1).getClass().getName().equals(f2[i].get(o2).getClass().getName())) {
                  // check if the class is Double,
                  // Integer or String
                  if (check(f1[i].get(o1).getClass().getName())) {
                    // compare values
                    if (!(f1[i].get(o1).equals(f2[i].get(o2)))) {
                      return false;
                    }
                  } else {
                    // special case, if the object is an
                    // linked list
                    if (f1[i].get(o1).getClass().getName().equals("java.util.LinkedList")) {
                      if (!(handleLinkedList(f1[i], o1, f2[i], o2))) {
                        return false;
                      }
                    } else {
                      // otherwise, compare the objects
                      structurallyEqual(f1[i].get(o1), f2[i].get(o2));
                    }
                  }
                } else {
                  return false;
                }
              } else {
                // if one of them is null, the objects can not
                // be equal
                if (f1[i].get(o1) == null && f2[i].get(o2) != null) {
                  return false;
                }
                if (f1[i].get(o1) != null && f2[i].get(o2) == null) {
                  return false;
                }
              }
            }
          }
        }
      } else {
        return false;
      }
    } catch (IllegalArgumentException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return true;
  }