1 package org.pojomatic.internal;
2
3 import java.lang.reflect.Method;
4 import java.lang.reflect.Modifier;
5 import java.util.*;
6
7
8
9
10
11 class OverridableMethods {
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 Set<PropertyRole> checkAndMaybeAddRolesToMethod(Method method, Set<PropertyRole> newRoles) {
28 Set<PropertyRole> existingRoles = findExistingRoles(method);
29 if (existingRoles.contains(PropertyRole.EQUALS)
30 && !existingRoles.contains(PropertyRole.HASH_CODE)
31 && newRoles.contains(PropertyRole.HASH_CODE)) {
32 throw new IllegalArgumentException(
33 "Method " + method.getDeclaringClass().getName() + "." + method.getName()
34 + " is requested to be included in hashCode computations, but already overrides a method"
35 + " which is requested for equals computations, but not hashCode computations.");
36 }
37 Set<PropertyRole> addedRoles = EnumSet.noneOf(PropertyRole.class);
38 for (PropertyRole role : newRoles) {
39 if (!existingRoles.contains(role)) {
40 addedRoles.add(role);
41 existingRoles.add(role);
42 }
43 }
44 return addedRoles;
45 }
46
47 private Set<PropertyRole> findExistingRoles(Method method) {
48 Set<PropertyRole> existingRoles;
49 if (isPackagePrivate(method)) {
50
51 PackageMethod key = new PackageMethod(method);
52 existingRoles = packageMethods.get(key);
53 if (existingRoles == null) {
54 existingRoles = EnumSet.noneOf(PropertyRole.class);
55 packageMethods.put(key, existingRoles);
56 }
57 }
58 else {
59
60
61
62 existingRoles = publicOrProtectedMethods.get(method.getName());
63 if (existingRoles == null) {
64 existingRoles = packageMethods.get(new PackageMethod(method));
65 }
66 if (existingRoles == null) {
67 existingRoles = EnumSet.noneOf(PropertyRole.class);
68 publicOrProtectedMethods.put(method.getName(), existingRoles);
69 }
70 }
71 return existingRoles;
72 }
73
74
75
76
77 private static class PackageMethod {
78 PackageMethod(Method method) {
79 name = method.getName();
80 pakage = method.getDeclaringClass().getPackage();
81 }
82
83 final String name;
84 final Package pakage;
85
86 @Override
87 public int hashCode() {
88 return name.hashCode() * 31 + pakage.hashCode();
89 }
90
91 @Override
92 public boolean equals(Object obj) {
93 if (this == obj) {
94 return true;
95 }
96 if (obj instanceof PackageMethod) {
97 PackageMethod other = (PackageMethod) obj;
98 return name.equals(other.name) && pakage.equals(other.pakage);
99 }
100 else {
101 return false;
102 }
103 }
104 }
105
106 private final Map<String, Set<PropertyRole>> publicOrProtectedMethods = new HashMap<>();
107 private final Map<PackageMethod, Set<PropertyRole>> packageMethods = new HashMap<>();
108
109
110 private static boolean isPackagePrivate(Method method) {
111 return !(Modifier.isPublic(method.getModifiers())
112 || Modifier.isProtected(method.getModifiers()));
113 }
114
115 }