1 package net.avcompris.commons3.core;
2
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static com.google.common.base.Preconditions.checkNotNull;
5
6 import java.lang.reflect.Array;
7 import java.lang.reflect.InvocationTargetException;
8 import java.lang.reflect.Method;
9 import java.util.HashMap;
10 import java.util.Map;
11
12 import com.google.common.collect.HashBasedTable;
13 import com.google.common.collect.Table;
14
15 import net.avcompris.commons3.api.EnumPermission;
16 import net.avcompris.commons3.api.EnumRole;
17 import net.avcompris.commons3.api.User;
18
19 public abstract class PermissionUtils<T extends EnumRole> {
20
21 private static final Table<EnumRole, EnumPermission, Boolean> CACHED_PERMISSION_TYPES = HashBasedTable.create();
22
23 private final Class<T> roleClass;
24
25 private final Map<String, EnumRole> roles = new HashMap<>();
26
27 public PermissionUtils(final Class<T> roleClass) {
28
29 this.roleClass = checkNotNull(roleClass, "roleClass");
30
31 checkArgument(roleClass.isEnum(),
32 "roleClass should be enum, but was: %s", roleClass.getName());
33
34 final Method valuesMethod;
35
36 try {
37
38 valuesMethod = roleClass.getMethod("values");
39
40 } catch (final NoSuchMethodException e) {
41 throw new IllegalStateException(e);
42 }
43
44 final Object values;
45
46 try {
47
48 values = valuesMethod.invoke(null);
49
50 } catch (final IllegalAccessException | InvocationTargetException e) {
51 throw new IllegalStateException(e);
52 }
53
54 final int count = Array.getLength(values);
55
56 for (int i = 0; i < count; ++i) {
57
58 final Object item = Array.get(values, i);
59
60 final EnumRole role = roleClass.cast(item);
61
62 roles.put(role.getRolename(), role);
63 }
64 }
65
66 public static boolean has(final User user, final EnumPermission permission) {
67
68 checkNotNull(user, "user");
69
70 return has(user.getRole(), permission);
71 }
72
73 public EnumRole getRole(final String rolename) {
74
75 checkNotNull(rolename, "rolename");
76
77 final EnumRole role = roles.get(rolename);
78
79 checkArgument(role != null,
80 "Unknown role: %s, in class: %s", rolename, roleClass.getName());
81
82 return role;
83 }
84
85 public static boolean has(final EnumRole role, final EnumPermission permission) {
86
87 checkNotNull(role, "role");
88 checkNotNull(permission, "permission");
89
90 final Boolean cached = CACHED_PERMISSION_TYPES.get(role, permission);
91
92 if (cached != null) {
93
94 return cached;
95 }
96
97 final boolean checked = check(role, permission);
98
99 CACHED_PERMISSION_TYPES.put(role, permission, checked);
100
101 return checked;
102 }
103
104 private static boolean check(final EnumRole role, final EnumPermission permission) {
105
106 for (final EnumRole superRole : role.getSuperRoles()) {
107
108 if (has(superRole, permission)) {
109
110 return true;
111 }
112 }
113
114 for (final EnumPermission p : role.getPermissions()) {
115
116 if (p == permission) {
117
118 return true;
119 }
120 }
121
122 return false;
123 }
124
125 public static void assertPermissionTypeClass(final Class<? extends EnumPermission> permissionTypeClass) {
126
127 checkNotNull(permissionTypeClass, "permissionTypeClass");
128
129 checkArgument(permissionTypeClass.isEnum(),
130 "permissionTypeClass should be Enum, but was: %s", permissionTypeClass.getName());
131 }
132 }