View Javadoc

1   package se.citerus.dddsample.domain.shared.experimental;
2   
3   import java.lang.reflect.Field;
4   
5   /**
6    * Base class for entities.
7    *
8    */
9   public abstract class EntitySupport<T extends Entity, ID> implements Entity<T, ID> {
10  
11      private static Field identityField;
12  
13      @Override
14      public final boolean sameIdentityAs(final T other) {
15          return other != null && this.identity().equals(other.identity());
16      }
17  
18      @Override
19      public final ID identity() {
20          if (identityField == null) {
21              identityField = identityFieldLazyDetermination(this.getClass());
22          }
23  
24          try {
25              return (ID) identityField.get(this);
26          } catch (IllegalAccessException e) {
27              throw new RuntimeException(e);
28          }
29      }
30  
31      private static Field identityFieldLazyDetermination(final Class cls) {
32          Field identityField = null;
33  
34          for (Field field : cls.getDeclaredFields()) {
35              if (field.getAnnotation(Identity.class) != null) {
36                  field.setAccessible(true);
37                  if (identityField != null) {
38                      throw new IllegalStateException("Only one field can be annotated with " + Identity.class);
39                  } else {
40                      identityField = field;
41                  }
42              }
43          }
44  
45          if (identityField == null) {
46              if (cls == Object.class) {
47                  throw new IllegalStateException(
48                    "This class, or one of its superclasses, " +
49                    "must have a unique field annotated with " + Identity.class);
50              } else {
51                  return identityFieldLazyDetermination(cls.getSuperclass());
52              }
53          }
54  
55          return identityField;
56      }
57  
58      @Override
59      public final int hashCode() {
60          return identity().hashCode();
61      }
62  
63      @Override
64      public final boolean equals(final Object o) {
65          if (this == o) return true;
66          if (o == null || getClass() != o.getClass()) return false;
67  
68          return sameIdentityAs((T) o);
69      }
70  
71  }